Hi,
Is it possible to remove an empty dir after a reboot ?
I need to reboot to remove a DLL.
I used the code :
Delete /REBOOTOK "$INSTDIR\mydll.dll"
After the reboot, my dll is deleted but I still have an empty directory : "c:\program files\myapp"
Is it possible to remove this directory (that's now empty and can then be removed successfully) ?
Thanks for your help
Chag
Removing empty dir after reboot
24 posts
AFAIK this isn't possible easily - hence all those empty folders in my Program Files folder 🙁
Couldn't you just do this?
Delete /REBOOTOK $INSTDIR\MyDLL.dll
Delete /REBOOTOK $INSTDIR
Adding an entry to the WININIT.INI file may work. I'm not sure how it works or if you can do it on NT systems, but something like:
or:WriteINIStr $WINDIR\WININIT.INI Rename Nul $INSTDIR
WriteINIStr $WINDIR\WININIT.INI Rename Nul $INSTDIR\NUL
Hi, i tried
and i'd liked to avoid modifying ini files.
but it doesn't work
Delete /REBOOTOK $INSTDIR
and i'd liked to avoid modifying ini files.
Try this:
and the "/r" switch will delete it recursively.
RMDir will delete the folder/directory. 🙂Delete /REBOOTOK "$INSTDIR\mydll.dll"
RMDir /r "$INSTDIR"
and the "/r" switch will delete it recursively.
Originally posted by SQwerlThe problem is if it has to reboot, RMDir /r "$INSTDIR" will never have a chance to run. Perhaps an /REBOOTOK option for RMDir is needed?
Try this:
RMDir will delete the folder/directory. 🙂Delete /REBOOTOK "$INSTDIR\mydll.dll"
RMDir /r "$INSTDIR"
and the "/r" switch will delete it recursively.
Robert
Old topic, but I have the same problem. Is there a solution now? A /REBOOTOK option for RMDir would be nice...
Oops 🙂 My mistake, I thought that this would be a problem, but the uninstaller runs from a different location or something, so Uninstall.exe can always be deleted.
Yea, it generates a couple of files in the TEMP folder in the WINDOWS Dir. That way, the Uninstaller can "self-delete" itself.
-Duane
-Duane
Originally posted by chagThis is how the /REBOOTOK option works.
i'd liked to avoid modifying ini files.
All of the installers I know use the WININIT.INI file to delete files on reboot. I just don't know how these things work on NT systems. I'd go to the Win98 computer but it's dead.
I'll do some research.
Originally posted by petersaThere is a registry location for it on WinNT systems.
This is how the /REBOOTOK option works.
All of the installers I know use the WININIT.INI file to delete files on reboot. I just don't know how these things work on NT systems. I'd go to the Win98 computer but it's dead.
I'll do some research.
I just tried a quick check using Registry Monitor, but I couldn't find anything...
Justin? How exactly does the /REBOOTOK option work? What registry or file changes does it involve?
Justin? How exactly does the /REBOOTOK option work? What registry or file changes does it involve?
Here is the function in the source code that is called if the /REBOOTOK flag appears.
KiCHiK
As you can see it writes to the WININIT.INI weather it's 9x or NT.BOOL MoveFileOnReboot(LPCTSTR pszExisting, LPCTSTR pszNew)
{
BOOL fOk = 0;
HMODULE hLib=LoadLibrary("kernel32.dll");
if (hLib)
{
typedef BOOL (WINAPI *mfea_t)(LPCSTR lpExistingFileName,LPCSTR lpNewFileName,DWORD dwFlags);
mfea_t mfea;
mfea=(mfea_t) GetProcAddress(hLib,"MoveFileExA");
if (mfea)
{
fOk=mfea(pszExisting, pszNew, MOVEFILE_DELAY_UNTIL_REBOOT|MOVEFILE_REPLACE_EXISTING);
}
FreeLibrary(hLib);
}
if (!fOk)
{
static char szRenameLine[1024];
static char wininit[1024];
static char tmpbuf[1024];
int cchRenameLine;
char *szRenameSec = "[Rename]\r\n";
HANDLE hfile, hfilemap;
DWORD dwFileSize, dwRenameLinePos;
static const char nulint[4]="NUL";
if (pszNew) GetShortPathName(pszNew,tmpbuf,1024);
else *((int *)tmpbuf) = *((int *)nulint);
// wininit is used as a temporary here
GetShortPathName(pszExisting,wininit,1024);
cchRenameLine = wsprintf(szRenameLine,"%s=%s\r\n",tmpbuf,wininit);
GetWindowsDirectory(wininit, 1024-16);
lstrcat(wininit, "\\wininit.ini");
hfile = CreateFile(wininit,
GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
if (hfile != INVALID_HANDLE_VALUE)
{
dwFileSize = GetFileSize(hfile, NULL);
hfilemap = CreateFileMapping(hfile, NULL, PAGE_READWRITE, 0, dwFileSize + cchRenameLine + 10, NULL);
if (hfilemap != NULL)
{
LPSTR pszWinInit = (LPSTR) MapViewOfFile(hfilemap, FILE_MAP_WRITE, 0, 0, 0);
if (pszWinInit != NULL)
{
int do_write=0;
LPSTR pszRenameSecInFile = findinmem(pszWinInit, szRenameSec,-1);
if (pszRenameSecInFile == NULL)
{
lstrcpy(pszWinInit+dwFileSize, szRenameSec);
dwFileSize += 10;
dwRenameLinePos = dwFileSize;
do_write++;
}
else
{
char *pszFirstRenameLine = findinmem(pszRenameSecInFile, "\n",-1)+1;
int l=pszWinInit + dwFileSize-pszFirstRenameLine;
if (!findinmem(pszFirstRenameLine,szRenameLine,l))
{
void* data=(void*)GlobalAlloc(GMEM_FIXED,l);
mini_memcpy(data, pszFirstRenameLine, l);
mini_memcpy(pszFirstRenameLine + cchRenameLine, data, l);
GlobalFree((HGLOBAL)data);
dwRenameLinePos = pszFirstRenameLine - pszWinInit;
do_write++;
}
}
if (do_write)
{
mini_memcpy(&pszWinInit[dwRenameLinePos], szRenameLine,cchRenameLine);
dwFileSize += cchRenameLine;
}
UnmapViewOfFile(pszWinInit);
fOk++;
}
CloseHandle(hfilemap);
}
SetFilePointer(hfile, dwFileSize, NULL, FILE_BEGIN);
SetEndOfFile(hfile);
CloseHandle(hfile);
}
}
return fOk;
}
KiCHiK
Thanks, KiCHiK, we're a step closer but I'm no programmer so this doesn't mean much to me. Any translators out there?
I'm guessing it adds a NUL=[file to delete] line to the [Rename] section of the $WINDIR\WININIT.INI file. How close am I?
I'm guessing it adds a NUL=[file to delete] line to the [Rename] section of the $WINDIR\WININIT.INI file. How close am I?
Almost 🙂 It only write NUL=... if it got pszNew as a null string. That means that can also rename to pszNew.
So when does it write pszNew?
It writes it when you use Rename /REBOOTOK. If you want to delete use NUL.
KiCHiK
KiCHiK
Okay, thanks KiCHiK! Now we all know how /REBOOTOK works, I reckon we could probably get rid of the functionality and put it into FUNCTIONS.HTM, or something?
One thing I don't understand, is why +2 is necessary instead of +1, i.e. [skip over the next 1 line].ClearErrors
Delete C:\WINDOWS\FileIn.Use
IfErrors 0 +2 ; if it was deleted then skip the next line
WriteINIStr $WINDIR\WININIT.INI Rename NUL C:\WINDOWS\FileIn.Use
Originally posted by petersaI belive it is because it means Goto 2 lines from here.. So if you did 1 it would goto the first line after it..
One thing I don't understand, is why +2 is necessary instead of +1, i.e. [skip over the next 1 line].
Originally posted by petersaa) The code in NSIS tries to do the remove-on-reboot the NT way and if that fails it drops back to the win9x way.
Okay, thanks KiCHiK! Now we all know how /REBOOTOK works, I reckon we could probably get rid of the functionality and put it into FUNCTIONS.HTM, or something?One thing I don't understand, is why +2 is necessary instead of +1, i.e. [skip over the next 1 line].ClearErrors
Delete C:\WINDOWS\FileIn.Use
IfErrors 0 +2 ; if it was deleted then skip the next line
WriteINIStr $WINDIR\WININIT.INI Rename NUL C:\WINDOWS\FileIn.Use
b)The WriteINIStr way won't work, because WriteINIStr will update
any entry that already begins with NUL=.
c) +2 is necessary because +1 jumps to the next instruction (+0 does the instruction again, +1 goes to next, +2 skips the next, etc).
-Justin
Oops... Sorry I mixed you up. I accidentally ignored the first block of code 🙁 😔
Right, so 0 and +0 are different...that makes sense then.
Okay, so how does the NT way work?
Okay, so how does the NT way work?
The NT way is MoveFileExA.
Read at MSDN on MoveFileEx and you will understand it all.
Read at MSDN on MoveFileEx and you will understand it all.