Winamp & Shoutcast Forums

Winamp & Shoutcast Forums (http://forums.winamp.com/index.php)
-   NSIS Discussion (http://forums.winamp.com/forumdisplay.php?f=65)
-   -   Next free drive letter (http://forums.winamp.com/showthread.php?t=271392)

Merlinovich 18th May 2007 21:50

Next free drive letter
 
I need to add a network drive for the next available drive letter.

I saw a post from Junior Member scatlin how to add drive Q: as a mapped network drive with the command
Exec '"net" "use" "Q:" "\\server\directory" ...'

However first I would like to *find* the next drive letter not in use. If I do it with Q: and the user has already mapped Q:, my user is in trouble (the installation will either overwrite what he has or abort, both of which are undesirable). I searched in the forum and help file of NSIS, but came up empty handed.

I could perhaps use {GetDrives} with some tedious looping. But I don't want to reinvent the wheel ...

Anders 18th May 2007 22:19

"net use * \\server\share" will use the next free drive letter.

Merlinovich 18th May 2007 22:27

Thanks, Anders! This works fine (kind of circumventing the problem) but now I need to know for the rest of my script which letter was assigned?

Afrow UK 19th May 2007 10:29

What is the output of that command?

Stu

Merlinovich 19th May 2007 13:28

Here is a small part of my NSIS script:

Exec '"net" "use" "*" "\\PM2000\ICIS5"'
...
; Configure ODBC data source GMS Central
WriteRegStr HKCU "Software\ODBC\ODBC.INI\ODBC Data Sources" "$Crop-CENTRAL-GMS" "Microsoft Access Driver (*.mdb)"
WriteRegStr HKCU "Software\ODBC\ODBC.INI\$Crop-CENTRAL-GMS" "DBQ" "X:\Database\$Crop\Central\$Crop-GMS.mdb"
WriteRegStr HKCU "Software\ODBC\ODBC.INI\$Crop-CENTRAL-GMS" "Driver" "$SYSDIR\odbcjt32.dll"
...

I'm setting up ODBC data sources to point to the newly created mapped network drive.
Now I would like to set X:\ to Q:\ above if Q:\ was the drive that was assigned in the net-command.

Afrow UK 19th May 2007 13:31

Like I said, does that command tell you anything when you execute it such as the drive that was mapped?

Stu

Merlinovich 19th May 2007 14:46

Oh, with "that command" you mean the "net use" command. Silly me. Didn't know the "net use" until I got it from scatlin and Anders.

Here is some documentation from Microsoft though:

http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/net_use.mspx?mfr=true
http://www.microsoft.com/resources/d....mspx?mfr=true

As far as I can tell, there is no output from the command, e.g. telling me which drive letter was assigned. I can use a bare "net use" command to get a list of connected drives, but that NSIS' GetDrives can also do, and the problem with that is that the files in the new drive could be identical to files in for instance C:\ or D:\ also (same subdirectories), and my script should not mix up these instances.

Afrow UK 19th May 2007 15:00

I guess you could compare the old list of drives with the new list to find out which one was added.
You could use NSISArray for that.

Stu

demiller9 19th May 2007 15:49

Here's the output of the net command that Stu is asking for:
code:
C:\Documents and Settings\Owner>net use * \\laptop\scc_d
Drive Z: is now connected to \\laptop\scc_d.

The command completed successfully.


I should point out that drive letter Z was not the 'next free drive letter' available to my way of thinking - my system only uses C (hard drive) and D (CD-ROM).

Don

Afrow UK 20th May 2007 10:43

Thank you. Something like this should get it.

code:

nsExec::ExecToStack 'net use * "\\PM2000\ICIS5"'
Pop $R0
StrCpy $R0 $R0 2 6


$R0 will contain Z:

You might want to do some validation checks on it though (i.e. check that it isn't empty!)

Stu

Merlinovich 22nd May 2007 15:12

Thanks for the feedback. I could never get the command nsExec::ExecToStack 'net use * "\\PM2000\ICIS5"' to work nor my first attempt Exec '"net" "use" "\\PM2000\ICIS5" ">out.txt"' where out.txt would be empty. Instead Exec '"net" "use" ">out.txt"' worked fine and produced a listing of drives as expected, but didn't help me of course.

Instead I opted for the NSISArray solution that Stu outlined. Here is the solution for anyone interested (sorry if I goofed up some command, I'm a newbie to NSIS):

code:

!include "NSISArray.nsh"
!include "LogicLib.nsh"
!include "FileFunc.nsh"
!include "WordFunc.nsh"
!include "TextFunc.nsh"
!insertmacro GetDrives
!insertmacro WordReplace
!insertmacro LineRead
Var /Global MappedDrive
${Array} "MyArray" 30 50
${ArrayFunc} Write
${ArrayFunc} Read
...
; Assign a mapped drive from \\PM2000\ICIS5
; automatically and put that in ODBC sources
; If it couldn't be assigned, then C:\ICIS5\... will be used
StrCpy $MappedDrive "C:\ICIS5"
; Check first if it was already assigned to some network
; drive, then recover that
${GetDrives} "NET" "RecoverMappedDrive"
; It wasn't found, so try to add it, recovering which
; drive letter was assigned
${If} $MappedDrive == "C:\ICIS5"
${MyArray->Init}
StrCpy $R1 0
${GetDrives} "NET" "SaveMappedDrives"
ExecWait '"net" "use" "*" "\\PM2000\ICIS5" "/persistent:yes"'
StrCpy $R1 0
${GetDrives} "NET" "GetMappedDriveLetter"
${MyArray->Delete}
${EndIf}
; Use of MappedDrive, which will either contain X: or C:\ICIS5
WriteRegStr HKCU "Software\ODBC\ODBC.INI\$Crop-CENTRAL-GMS" "DBQ" \
"$MappedDrive\Database\$Crop\Central\$Crop-GMS.mdb"
SectionEnd

; Check if X:\EXES\ICIS32.DLL exists (which it will if the
; network directory was already mapped to X: )
Function RecoverMappedDrive
IfFileExists $9EXES\ICIS32.DLL 0 +3
StrCpy $MappedDrive $9 1
StrCpy $MappedDrive "$MappedDrive:"
Push $0
FunctionEnd

Function SaveMappedDrives
${MyArray->Write} $R1 $9
IntOp $R1 $R1 + 1
Push $0
FunctionEnd

Function GetMappedDriveLetter
${MyArray->Read} $R2 $R1
IntOp $R1 $R1 + 1
${If} $MappedDrive == "C:\ICIS5"
StrCmp $9 $R2 +3 0
StrCpy $MappedDrive $9 1
StrCpy $MappedDrive "$MappedDrive:"
${EndIf}
Push $0
FunctionEnd


Afrow UK 22nd May 2007 17:01

I'm sorry, this code works much better :p

code:

ReadEnvStr $R0 COMSPEC
nsExec::ExecToStack '$R0 /C net use * "\\PC-01\Drive-C\NewPCTemp"'
Pop $R0

StrCmp $R0 0 +4
Pop $R0
DetailPrint $R0
Abort

Pop $R0
StrCpy $MappedDrive $R0 2 6



Stu

Merlinovich 22nd May 2007 17:13

There might still be a problem with the exact location of the drive in the string, when using e.g. Spanish Windows or another regional Windows version. Perhaps this can be mended best by searching for ':' in the string, because that probably is independent of region (well, don't know about chinese!), so the drive letter will be just before ':'.

Thanks for the alternative. My solution had the added benefit of introducing me to NSISarray that I think will be very useful for me in the future.

Afrow UK 22nd May 2007 17:38

Good point. Let me see what I can do.
I just think the other solution is a bit dodgy because it's not direct.

Stu

Afrow UK 22nd May 2007 17:44

Here we are.
code:

ReadEnvStr $R0 COMSPEC
nsExec::ExecToStack '$R0 /C net use * "\\PC-01\Drive-C\NewPCTemp"'
Pop $R0

StrCmp $R0 0 +4
Pop $R0
DetailPrint $R0
Abort

Pop $R0
StrCpy $R1 0
StrLen $R3 $R0

StrCpy $R2 $R0 1 $R1
StrCmp $R1 $R3 0 +3
DetailPrint "Error: Mapped network drive could not be located."
Abort
IntOp $R1 $R1 + 1
StrCmp $R2 : 0 -5
IntOp $R1 $R1 - 2

StrCpy $MappedDrive $R0 2 $R1



Stu

bnicer 23rd May 2007 14:29

Wow! Is there nothing NSIS can't do? Returning the output from a command prompt! I've used comspec, command.com and cmd.exe in vbScript. So I hope this isn't wrong. All credit goes to Stu for the solution. I noticed with cmd.exe the /c switch halts the script, and since you're running the commandline via another process, I don't know if you need to close the dos box. It may not even open. I also tried comspec with /k which is supposed to keep the window open and it doesn't.

Afrow UK 23rd May 2007 14:34

nsExec hides the command prompt window and it has to wait for the execution to complete to get the exit code and output.

This code will work if the output contains unicode characters as well.

%COMSPEC% is what you should use because command prompt can be cmd.exe or command.com depending on the operating system.

Stu

Merlinovich 24th May 2007 04:43

Yes, NSIS is versatile :)

I tried your new code (Stu) and it works fine in my desktop computer, even with a Spanish Windows version. So just when I thought the discussion was over, I stumbled over a case where my old version would work better. Perhaps Stu's code can be mended too to handle this case:

I was trying to install on a Linux machine (VMWare) that has Windows XP as a subsystem (don't know the right term), and that Windows subsystem didn't allow the connection to the network drive without (LAN) username and password. So my installation with Stu's code just failed, while the old code "worked" to my surprise, because the old DOS window would then ask for username and password from the command prompt, and entering these, in fact *did* connect the network drive.

I realize the "net use /username:<> /password:<>" is possible, but then I only have this kind of problem in 5% of my company's computers, the rest will connect automatically, and then it would be tedious in the 95% of cases to ask the user for LAN username and password. One drawback to the DOS window is that it is a bit ugly and distracting user attention, looks non-professional.

Afrow UK 24th May 2007 15:15

If it fails then perhaps you could ask for a username and password (which you would have to write a small plugin for).

I'll have a look at not using cmd.exe.

Stu

Afrow UK 24th May 2007 15:17

Hmm it seems to be ok now I get 0 on success without using cmd.exe.

code:

nsExec::ExecToStack 'net use * "\\PC-01\Drive-C\NewPCTempo"'
Pop $R0

StrCmp $R0 0 +4
Pop $R0
DetailPrint $R0
Abort

Pop $R0
StrCpy $R1 0
StrLen $R3 $R0

StrCpy $R2 $R0 1 $R1
StrCmp $R1 $R3 0 +3
DetailPrint "Error: Mapped network drive could not be located."
Abort
IntOp $R1 $R1 + 1
StrCmp $R2 : 0 -5
IntOp $R1 $R1 - 2

StrCpy $MappedDrive $R0 2 $R1



Stu


All times are GMT. The time now is 04:40.

Copyright © 1999 - 2010 Nullsoft. All Rights Reserved.