- NSIS Discussion
- Removing empty dir after reboot
Archive: Removing empty dir after reboot
chag
22nd December 2001 22:37 UTC
Removing empty dir after reboot
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
Koen van de Sande
23rd December 2001 09:06 UTC
AFAIK this isn't possible easily - hence all those empty folders in my Program Files folder :(
petersa
25th December 2001 09:30 UTC
Couldn't you just do this?
Delete /REBOOTOK $INSTDIR\MyDLL.dll
Delete /REBOOTOK $INSTDIR
petersa
25th December 2001 09:32 UTC
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:
WriteINIStr $WINDIR\WININIT.INI Rename Nul $INSTDIR
or:
WriteINIStr $WINDIR\WININIT.INI Rename Nul $INSTDIR\NUL
chag
3rd January 2002 20:32 UTC
Hi, i tried
Delete /REBOOTOK $INSTDIR
but it doesn't work
and i'd liked to avoid modifying ini files.
SQwerl
4th January 2002 02:48 UTC
Try this:
Delete /REBOOTOK "$INSTDIR\mydll.dll"
RMDir /r "$INSTDIR"
RMDir will delete the folder/directory. :)
and the "/r" switch will delete it recursively.
rainwater
4th January 2002 04:16 UTC
Originally posted by SQwerl
Try this:
Delete /REBOOTOK "$INSTDIR\mydll.dll"
RMDir /r "$INSTDIR"
RMDir will delete the folder/directory. :)
and the "/r" switch will delete it recursively.
The 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?
Robert
Joost Verburg
4th January 2002 23:25 UTC
Old topic, but I have the same problem. Is there a solution now? A /REBOOTOK option for RMDir would be nice...
Joost Verburg
5th January 2002 14:40 UTC
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.
DuaneJeffers
6th January 2002 03:44 UTC
Yea, it generates a couple of files in the TEMP folder in the WINDOWS Dir. That way, the Uninstaller can "self-delete" itself.
-Duane
petersa
6th January 2002 06:11 UTC
Originally posted by chag
i'd liked to avoid modifying ini files.
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.
Joost Verburg
6th January 2002 13:15 UTC
Originally posted by petersa
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.
There is a registry location for it on WinNT systems.
petersa
9th January 2002 13:22 UTC
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?
kichik
9th January 2002 13:51 UTC
Here is the function in the source code that is called if the /REBOOTOK flag appears.
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;
}
As you can see it writes to the WININIT.INI weather it's 9x or NT.
KiCHiK
petersa
9th January 2002 14:30 UTC
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?
kichik
9th January 2002 14:54 UTC
Almost :) It only write NUL=... if it got pszNew as a null string. That means that can also rename to pszNew.
petersa
11th January 2002 13:11 UTC
So when does it write pszNew?
kichik
11th January 2002 13:17 UTC
It writes it when you use Rename /REBOOTOK. If you want to delete use NUL.
KiCHiK
petersa
11th January 2002 13:23 UTC
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?
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
One thing I don't understand, is why +2 is necessary instead of +1, i.e. [
skip over the next 1 line].
Schultz
11th January 2002 13:47 UTC
Originally posted by petersa
One thing I don't understand, is why +2 is necessary instead of +1, i.e. [skip over the next 1 line].
I belive it is because it means
Goto 2 lines from here.. So if you did 1 it would goto the first line after it..
justin
12th January 2002 04:55 UTC
Originally posted by petersa
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?
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
One thing I don't understand, is why +2 is necessary instead of +1, i.e. [skip over the next 1 line].
a) 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.
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
kichik
12th January 2002 09:43 UTC
Oops... Sorry I mixed you up. I accidentally ignored the first block of code :( :hang:
petersa
12th January 2002 09:57 UTC
Right, so 0 and +0 are different...that makes sense then.
Okay, so how does the NT way work?
kichik
12th January 2002 10:37 UTC
The NT way is MoveFileExA.
Read at MSDN on MoveFileEx and you will understand it all.