我正在试图弄清楚如何使用Pascal Script / Inno Setup中的WinAPI函数。我没有找到很多代码示例如何做到这一点,我不是一个Pascal程序员。这是我到目前为止所做的:
导入功能
public class InstallAPK extends AsyncTask<Void,Integer,Void> {
ProgressDialog progressDialog;
int status = 0;
private Context context;
public InstallAPK(Context context, ProgressDialog progress){
this.context = context;
this.progressDialog = progress;
}
public void onPreExecute() {
if(progressDialog!=null)
progressDialog.show();
}
@Override
protected Void doInBackground(Void... arg0) {
try {
URL url = new URL(context.getString(R.string.kodi_apk_link));
HttpURLConnection c = (HttpURLConnection) url.openConnection();
c.setRequestMethod("GET");
c.setDoOutput(true);
c.connect();
// getting file length
int lenghtOfFile = c.getContentLength();
Log.e("File length", ""+lenghtOfFile);
File outputFile = new File(context.getFilesDir(), context.getString(R.string.kodi_apk_name));
if(outputFile.exists()){
if(outputFile.length() != lenghtOfFile)
outputFile.delete();
else {
publishProgress(-1);
final String libs = "LD_LIBRARY_PATH=/vendor/lib:/system/lib ";
final String commands = libs + "pm install -r " + context.getFilesDir().getAbsolutePath() + "/"
+ context.getString(R.string.kodi_apk_name);
installApk(commands);
return null;
}
}
FileOutputStream fos = new FileOutputStream(outputFile);
InputStream is = c.getInputStream();
//i tried both, with and without buffered reader
BufferedInputStream bufferedInputStream = new BufferedInputStream(is);
byte[] buffer = new byte[1024];
int len1 = 0, total=0;
if (lenghtOfFile != -1)
{
buffer = new byte[lenghtOfFile];
do {
len1 += bufferedInputStream.read(buffer, len1, lenghtOfFile-len1);
publishProgress((int)((len1*100)/lenghtOfFile));
} while (len1 < lenghtOfFile);
}
//I was using this code before, but it's not working too
/*while ((len1 = is.read(buffer)) != -1) {
total += len1;
publishProgress((int)((total*100)/lenghtOfFile));
fos.write(buffer, 0, len1);
}*/
fos.flush();
fos.close();
bufferedInputStream.close();
is.close();
//Log.e("Directory path", myDir.getAbsolutePath());
publishProgress(-1);
final String libs = "LD_LIBRARY_PATH=/vendor/lib:/system/lib ";
final String commands = libs + "pm install -r " + context.getFilesDir().getAbsolutePath() + "/"
+ context.getString(R.string.kodi_apk_name);
installApk(commands);
} catch (FileNotFoundException fnfe) {
status = 1;
Log.e("File", "FileNotFoundException! " + fnfe);
}
catch(Exception e)
{
Log.e("UpdateAPP", "Exception " + e);
}
return null;
}
protected void onProgressUpdate(Integer... progress) {
if(progress[0]!=-1) {
// setting progress percentage
progressDialog.setProgress(progress[0]);
} else {
progressDialog.setIndeterminate(true);
progressDialog.setMessage("Installing Kodi...");
}
}
public void onPostExecute(Void unused) {
if(progressDialog!=null) {
progressDialog.dismiss();
}
if(status == 1)
Toast.makeText(context,"App Not Available",Toast.LENGTH_LONG).show();
else
Toast.makeText(context,"Successfully installed the app",Toast.LENGTH_LONG).show();
Intent LaunchIntent = context.getPackageManager().getLaunchIntentForPackage(context.getString(R.string.kodi_apk_package));
if(LaunchIntent!=null)
context.startActivity(LaunchIntent);
else
Toast.makeText(context, "Error in installig Kodi, Try again.", Toast.LENGTH_LONG).show();
}
private void installApk(String commands) {
try {
Process p = Runtime.getRuntime().exec("su");
InputStream es = p.getErrorStream();
DataOutputStream os = new DataOutputStream(p.getOutputStream());
os.writeBytes(commands + "\n");
os.writeBytes("exit\n");
os.flush();
int read;
byte[] buffer = new byte[4096];
String output = new String();
while ((read = es.read(buffer)) > 0) {
output += new String(buffer, 0, read);
}
Log.v("AutoUpdaterActivity", output.toString());
p.waitFor();
} catch (IOException e) {
Log.v("AutoUpdaterActivity", e.toString());
} catch (InterruptedException e) {
Log.v("AutoUpdaterActivity", e.toString());
}
}
}
并像这样使用它:
function PathCombine (
pszPathOut : PChar;
pszPathIn : PChar;
pszMore : PChar
) : PChar;
external 'PathCombineA@Shlwapi.dll stdcall';
输出是这样的:
预期输出为:
C:\一个\ 2
我很确定我在内存中访问垃圾值,但我不知道为什么,我该如何解决?
答案 0 :(得分:2)
您没有指定是否使用Ansi或Unicode版本的Inno Setup。
但这应该适用于任何一个版本:
function PathCombine(
pszPathOut : PAnsiChar;
pszPathIn : PAnsiChar;
pszMore : PAnsiChar
) : PAnsiChar; external 'PathCombineA@Shlwapi.dll stdcall';
function InitializeSetup(): Boolean;
var
a, b, c: AnsiString;
begin
SetLength(c, 256); { soon it gets working I'll switch to use MAX_PATH instead of }
a := 'C:';
b := 'one\two';
PathCombine(c, a, b);
MsgBox(c, mbInformation, MB_OK);
Result := True;
end;
虽然我强烈建议您改为使用Unicode version of Inno Setup和PathCombineW
。
function PathCombine(
pszPathOut : string;
pszPathIn : string;
pszMore : string
) : Cardinal; external 'PathCombineW@Shlwapi.dll stdcall';
function InitializeSetup(): Boolean;
var
a, b, c: string;
begin
SetLength(c, 256); { soon it gets working I'll switch to use MAX_PATH instead of }
a := 'C:';
b := 'one\two';
PathCombine(c, a, b);
MsgBox(c, mbInformation, MB_OK);
Result := True;
end;
请注意,Inno Setup缺少PWideChar
类型。虽然它可以封送string
到LPTSTR
(PWideChar
)函数参数,但它不能封送LPTSTR
返回值。所以我使用Cardinal
作为返回类型。它与指针(对于char)具有相同的大小,因此堆栈将匹配。我们实际上并不需要返回的值。
答案 1 :(得分:-1)
我认为(虽然我还没有使用 Pascal / Delphi 一段时间)问题是 C “字符串” (char *
) 0 基于索引,而 Pascal 字符串 1 基于索引(字节 0 用于存储长度)。
因此,如果您将s
变量声明为:
s: array[0..255] of Char; //Don't forget to change it to MAX_PATH afterwards
它应该有用。也可以像这样使用PathCombine
函数:
PathCombine(s, a, b);
无需将其结果(与s
相同)分配给另一个变量(无论如何都不会使用)。