Inno Setup:生成的文件夹名称适用于 Windows XP 但不适用于 Windows 7
Inno Setup: Generated folder name works in Windows XP but not Windows 7
在 [Files] 部分,我使用调用我自己的 DLL 的 Pascal 脚本来生成一个文件夹名称,我希望在其中安装我的程序文档。我的 DLL 和我的 Pascal 脚本似乎工作正常,但是当我 运行 我的安装程序在 Windows 7 上时,Inno Setup 使用目录名作为文件名而不是将文件名附加到目录名,我最终将所有 3 个文档文件复制到一个文件中,该文件具有我希望目录具有的名称。奇怪的是,当我在 Windows XP 上 运行 时,代码确实可以正常工作。
这里是一些相关的代码:
[文件] 部分:
[Files]
Source: "doc 1.pdf"; DestDir: "{code:DocumentFolder}";
Source: "doc 2.pdf"; DestDir: "{code:DocumentFolder}";
Source: "doc 3.pdf"; DestDir: "{code:DocumentFolder}";
Pascal 脚本:
// Get the path to the documentation folder
// DocPath() returns a path name without a trailing backslash
// unless it returns a null string.
function DocumentFolder(Param: String) : String;
var
s : String;
k : integer;
begin
SetLength(s, 255);
k := DocPath(s); // Path to "MyCompany\MyProg" folder or something like it
if 0 = k then s := ExpandConstant('{app}'); // Just use the program folder if there is no public folder
Result := s;
end;
我编写脚本的原因是我希望将文档放入系统 public 文件夹中的一个文件夹(如果有),但交替放入系统上的程序文件夹中没有 public 个文件夹。
如果我错过了一些完全简单的方法,请告诉我。
无论如何,当我在 Windows 7 系统上 运行 时,根据 Inno Setup 的调试日志,这是我得到的:
[10:47:42.406] Dest filename: C:\Users\Public\MyCompany\MyProgDocs
[10:47:42.409] Time stamp of our file: 2002-07-10 10:33:02.000
[10:47:42.412] Installing the file.
[10:47:42.453] Successfully installed the file.
[10:47:42.458] -- File entry --
[10:47:44.595] Dest filename: C:\Users\Public\MyCompany\MyProgDocs
[10:47:44.598] Time stamp of our file: 2014-09-13 21:14:36.000
[10:47:44.600] Dest file exists.
[10:47:44.601] Time stamp of existing file: 2002-07-10 10:33:02.000
[10:47:44.603] Version of our file: (none)
[10:47:44.609] Version of existing file: (none)
[10:47:44.611] Installing the file.
[10:47:44.637] Successfully installed the file.
[10:47:44.640] -- File entry --
[10:47:45.603] Dest filename: C:\Users\Public\MyCompany\MyProgDocs
[10:47:45.606] Time stamp of our file: 2014-09-16 14:51:26.000
[10:47:45.608] Dest file exists.
[10:47:45.610] Time stamp of existing file: 2014-09-13 21:14:36.000
[10:47:45.612] Version of our file: (none)
[10:47:45.615] Version of existing file: (none)
[10:47:45.617] Installing the file.
[10:47:45.710] Successfully installed the file.
如您所见,我的 3 个 PDF 文件中的每一个都已被复制到一个名为 C:\Users\Public\MyCompany\MyProgDocs
的文件中,而不是我预期的 C:\Users\Public\MyCompany\MyProgDocs\doc 1.pdf
等。目标文件由 [Files] 部分中的第一行创建,然后被第二行覆盖,然后再次被第三行覆盖。
通过调试器,我看到我的 Pascal 脚本和支持它的 DLL 工作正常。
调用DocPath(s)
returns字符串中的字符数,并将其参数s
设置为我想要的字符串值。在 XP 上,它 returns 一个零并将 s
设置为空字符串。在 Windows 7、DocPath(s)
returns 36 上并将 s
设置为 C:\Users\Public\MyCompany\MyProgDocs
。
我该如何解决这个问题?
编辑:
这是我的 DLL 中的一些相关代码:
#define FOLDERNAME _T("MyCompany")
static CString GetPublicPath()
{
TCHAR pubpath[_MAX_PATH] = {_T("")};
int nameSize = ::GetEnvironmentVariable(_T("public"), pubpath, countof(pubpath));
if (0 < nameSize)
{
TCHAR* wdbuf = _tgetcwd(NULL, 0);
_tchdir(pubpath);
_tmkdir(FOLDERNAME);
_tchdir(FOLDERNAME);
_tcscat(pubpath, _T("\"));
_tcscat(pubpath, FOLDERNAME);
_tchdir(wdbuf);
free(wdbuf);
}
return CString(pubpath);
}
int STDCALL DocPath(wchar_t** x)
{
CString docpath = GetPublicPath();
docpath = StripBackslash(docpath);
if (0 < docpath.GetLength())
{
docpath += _T("\MyProgDocs");
}
_tcscpy(*x, docpath.GetBuffer());
::MessageBox(0, *x, _T("DLL DocPath()"), MB_OK);
return _tcslen(*x);
}
我在生产版本中没有对 MessageBox()
的调用,但它对调试很有用。宏 countof
类似于 sizeof
但 returns 是数组计数而不是字节大小,因此它适用于宽字符。
如果 k > 0 您必须将 s 的长度设置为 k。
但是从内部获取环境变量要容易得多(并且不必编写dll) - 例如:
function DocumentFolder(dummy: String): String;
var
s: String;
begin
s := GetEnv('public');
if Length(s) > 0 then
s := s + '\MyCompany\MyProgDocs'
else
s := ExpandConstant('{app}');
Result := s;
end;
在 [Files] 部分,我使用调用我自己的 DLL 的 Pascal 脚本来生成一个文件夹名称,我希望在其中安装我的程序文档。我的 DLL 和我的 Pascal 脚本似乎工作正常,但是当我 运行 我的安装程序在 Windows 7 上时,Inno Setup 使用目录名作为文件名而不是将文件名附加到目录名,我最终将所有 3 个文档文件复制到一个文件中,该文件具有我希望目录具有的名称。奇怪的是,当我在 Windows XP 上 运行 时,代码确实可以正常工作。
这里是一些相关的代码:
[文件] 部分:
[Files]
Source: "doc 1.pdf"; DestDir: "{code:DocumentFolder}";
Source: "doc 2.pdf"; DestDir: "{code:DocumentFolder}";
Source: "doc 3.pdf"; DestDir: "{code:DocumentFolder}";
Pascal 脚本:
// Get the path to the documentation folder
// DocPath() returns a path name without a trailing backslash
// unless it returns a null string.
function DocumentFolder(Param: String) : String;
var
s : String;
k : integer;
begin
SetLength(s, 255);
k := DocPath(s); // Path to "MyCompany\MyProg" folder or something like it
if 0 = k then s := ExpandConstant('{app}'); // Just use the program folder if there is no public folder
Result := s;
end;
我编写脚本的原因是我希望将文档放入系统 public 文件夹中的一个文件夹(如果有),但交替放入系统上的程序文件夹中没有 public 个文件夹。
如果我错过了一些完全简单的方法,请告诉我。
无论如何,当我在 Windows 7 系统上 运行 时,根据 Inno Setup 的调试日志,这是我得到的:
[10:47:42.406] Dest filename: C:\Users\Public\MyCompany\MyProgDocs
[10:47:42.409] Time stamp of our file: 2002-07-10 10:33:02.000
[10:47:42.412] Installing the file.
[10:47:42.453] Successfully installed the file.
[10:47:42.458] -- File entry --
[10:47:44.595] Dest filename: C:\Users\Public\MyCompany\MyProgDocs
[10:47:44.598] Time stamp of our file: 2014-09-13 21:14:36.000
[10:47:44.600] Dest file exists.
[10:47:44.601] Time stamp of existing file: 2002-07-10 10:33:02.000
[10:47:44.603] Version of our file: (none)
[10:47:44.609] Version of existing file: (none)
[10:47:44.611] Installing the file.
[10:47:44.637] Successfully installed the file.
[10:47:44.640] -- File entry --
[10:47:45.603] Dest filename: C:\Users\Public\MyCompany\MyProgDocs
[10:47:45.606] Time stamp of our file: 2014-09-16 14:51:26.000
[10:47:45.608] Dest file exists.
[10:47:45.610] Time stamp of existing file: 2014-09-13 21:14:36.000
[10:47:45.612] Version of our file: (none)
[10:47:45.615] Version of existing file: (none)
[10:47:45.617] Installing the file.
[10:47:45.710] Successfully installed the file.
如您所见,我的 3 个 PDF 文件中的每一个都已被复制到一个名为 C:\Users\Public\MyCompany\MyProgDocs
的文件中,而不是我预期的 C:\Users\Public\MyCompany\MyProgDocs\doc 1.pdf
等。目标文件由 [Files] 部分中的第一行创建,然后被第二行覆盖,然后再次被第三行覆盖。
通过调试器,我看到我的 Pascal 脚本和支持它的 DLL 工作正常。
调用DocPath(s)
returns字符串中的字符数,并将其参数s
设置为我想要的字符串值。在 XP 上,它 returns 一个零并将 s
设置为空字符串。在 Windows 7、DocPath(s)
returns 36 上并将 s
设置为 C:\Users\Public\MyCompany\MyProgDocs
。
我该如何解决这个问题?
编辑: 这是我的 DLL 中的一些相关代码:
#define FOLDERNAME _T("MyCompany")
static CString GetPublicPath()
{
TCHAR pubpath[_MAX_PATH] = {_T("")};
int nameSize = ::GetEnvironmentVariable(_T("public"), pubpath, countof(pubpath));
if (0 < nameSize)
{
TCHAR* wdbuf = _tgetcwd(NULL, 0);
_tchdir(pubpath);
_tmkdir(FOLDERNAME);
_tchdir(FOLDERNAME);
_tcscat(pubpath, _T("\"));
_tcscat(pubpath, FOLDERNAME);
_tchdir(wdbuf);
free(wdbuf);
}
return CString(pubpath);
}
int STDCALL DocPath(wchar_t** x)
{
CString docpath = GetPublicPath();
docpath = StripBackslash(docpath);
if (0 < docpath.GetLength())
{
docpath += _T("\MyProgDocs");
}
_tcscpy(*x, docpath.GetBuffer());
::MessageBox(0, *x, _T("DLL DocPath()"), MB_OK);
return _tcslen(*x);
}
我在生产版本中没有对 MessageBox()
的调用,但它对调试很有用。宏 countof
类似于 sizeof
但 returns 是数组计数而不是字节大小,因此它适用于宽字符。
如果 k > 0 您必须将 s 的长度设置为 k。 但是从内部获取环境变量要容易得多(并且不必编写dll) - 例如:
function DocumentFolder(dummy: String): String;
var
s: String;
begin
s := GetEnv('public');
if Length(s) > 0 then
s := s + '\MyCompany\MyProgDocs'
else
s := ExpandConstant('{app}');
Result := s;
end;