I have a Winforms application that I want to publish using ClickOnce. This application comes with an initial database, which must be installed once on a per-machine basis. After much ado, I have landed on the idea of using a custom pre-requisite to install the .sdf file. I have used Bootstrapper Manifest Generator (BMG) to create a package for the .cmd file I want to run, and I have included the .sdf file as an "additional file."
My expectation was that the two files would end up in the same directory, and I would be able to copy the .sdf file to the place where I want it (They do end up in the same directory.) The pre-requisite shows up in Visual Studio just fine. It get's deployed to the client system just fine, and the setup program kicks off the prerequisite just fine.
The only problem is that the current working directory that the .cmd file is executing is C:\Documents and Settings\\Desktop!
Neither of the two files (.cmd or .sdf) are located there - they were downloaded elsewhere, e.g., "C:\Documents and Settings\drogers\Local Settings\Temp\VSD5A.tmp". So, although I know where to xcopy to, I have no idea where to xcopy from.
How can I resolve this?
Here is the .cmd file:
REM Modify this file to reflect your manufacturer name [FHCRC] and product name [ClickOnceSharedDataDemo].
SET TargetBase=%ALLUSERSPROFILE%
IF NOT "%TargetBase%"=="C:\ProgramData" SET TargetBase=%ALLUSERSPROFILE%\Application Data
REM We only want to do this copy for the first user!
if exist "%TargetBase%\FHCRC\ClickOnceSharedDataDemo\shareddata.sdf" GOTO EXIT
if not exist "%TargetBase%\FHCRC" mkdir "%TargetBase%\FHCRC"
if not exist "%TargetBase%\FHCRC\ClickOnceSharedDataDemo" mkdir "%TargetBase%\FHCRC\ClickOnceSharedDataDemo"
CACLS "%TargetBase%\FHCRC\ClickOnceSharedDataDemo" /E /T /C /G "Users":C
xcopy shareddata.sdf "%TargetBase%\FHCRC\ClickOnceSharedDataDemo\"
if not exist "%TargetBase%\FHCRC\ClickOnceSharedDataDemo\shareddata.sdf" PAUSE
if not exist "%TargetBase%\FHCRC\ClickOnceSharedDataDemo\shareddata.sdf" exit /B -1
:EXIT
PAUSE
exit /B 0
Thanks,
David
Well, I am not altogether happy with this solution, but it works. I now have two prerequisites. the first is just the command file which runs the CACLS commands to set permissions. It is basically a shortened version of the above:
REM Modify this file to reflect your manufacturer name [Manufacturer] and product name [ProductName].
SET TargetBase=%ALLUSERSPROFILE%
IF NOT "%TargetBase%"=="C:\ProgramData" SET TargetBase=%ALLUSERSPROFILE%\Application Data
REM We only want to do this copy for the first user!
if exist "%TargetBase%\Manufacturer\ProductName\shareddata.sdf" GOTO EXIT
if not exist "%TargetBase%\Manufacturer" mkdir "%TargetBase%\Manufacturer"
if not exist "%TargetBase%\Manufacturer\ProductName" mkdir "%TargetBase%\Manufacturer\ProductName"
CACLS "%TargetBase%\Manufacturer\ProductName" /E /T /C /G "Users":C
:EXIT
ECHO exit /B 0
The second prerequisite is an "all users = true" setup project which has a custom folder located at default location:
"[CommonAppDataFolder][Manufacturer][ProductName]".
Into this folder I put the sdf file.
Finally, I used Bootstrapper Manifest Generator to make packages for both, making the second dependent on the first. I copied the packages to the appropriate VS2010 directory, included them as prerequisites, and published.
I now have per-machine .sdf files published to both WinXP and Win7. Why does this have to be so difficult!?!?
I'm still looking for less complicated solutions, that will install to both Windows 7 and Windows XP.
Did you try MSDeploy? It is able to fulfil all your needs.
Cheers!
You could just include the .sdf file with the ClickOnce application, then have your program copy it to somewhere else the first time it runs. I never recommend keeping the data in the CLickOnce cache anyway, it's safer to handle it yourself. See if this article helps at all:
http://robindotnet.wordpress.com/2009/08/19/where-do-i-put-my-data-to-keep-it-safe-from-clickonce-updates/
Related
So, there is always one installer (msi) in a folder for install generation, but the name changes many times. I tried doing the following:
"C:\Windows\system32\msiexec.exe" /i "C:\test\*.msi" /qn
But sadly, this doesn't work and complains. How can we get the name of the single msi in the folder, and plonk it into the command?
I'm using jenkins and using the "Execute windows batch command" item
Perhaps use a for loop to find all .msi files in that directory, and run it accordingly (obviously if there is more than one .msi you will need to tweak this logic):
for /r "C:\test" %%a in (*.msi) do msiexec /i "%%~dpnxa" /qn
I have a really messy program in my environment that basically has a jump client on over 7000 machines in my environment. When I upgrade the appliance that the jump client talks to it starts an in place upgrade but if there are computers off or off the network obviously the upgrade times out. Problem is, I cant mass deploy the updated jump client because the previous version has to be uninstalled first.
WMIC uninstaller doesn't work, msiexec uninstaller doesn't work. There is a batch file built into the program stored at %ProgramData%\ClientNameRandomNumbers. Problem is, you can also install a dissolvable client in the moment if needed and everytime the dissolvable client installs, it doesn't clean up after itself. So you have random folders that may or may not be the one that contains the uninstall.bat batch file that I need to run. I wanted to write a script to mass deploy that will start that batch file on each computer but I am having problems.
Basically I want it to search for the folder with a wild card, if it finds it CD to that directory and then try to run the uninstall, if it can't find the uninstall, continue through to deleting the folder as it is an old shell folder. And then go back and look for more folders until it can't find anymore and then go to exit.
This is what I have:
:START
cd %programdata%\bomgar-scc* || IF ERRORLEVEL not = 0 GOTO END
start uninstall.bat /Wait || cd c:\programdata &&
rd C:\programdata\bomgar-scc*
GOTO START
pause
:END
EXIT
Any suggestions?
I think I am understanding your requirements but maybe not. I have commented the code to let you know what it is doing.
#echo off
REM For command will attempt to find all folders
REM that start with bomgar-scc in the programdata folder
for /d %%G IN ("%programdata%\bomgar-scc*") do (
REM If it finds a folder check if an uninstall.bat
REM exists and run the batch file if it does exist.
IF EXIST "%%~G\uninstall.bat" CALL "%%~G\uninstall.bat"
REM Remove the directory found
rd "%%~G"
)
Create a Jump client MSI installer. Run the following command to uninstall it.
msiexec.exe /x "\%networkpath%\bomgar-scc-win64.msi" /quiet
done a search on this, but little joy. I am making and later, trying to delete a folder in the same batch file:
mkdir "%_gameKey%"
:: Stuff.....
rmdir /s /q "%_gameKey%"
I get the error "the process cannot access the file because it is being used by another process." I also can't delete the folder via right-click delete - same error. Interestingly, the rmdir removes the contents of the folder. There is nothing in the folder, nor is there anything obvious accessing it.
I have used Unlocker - shows no processes. Have also used Process Explorer, searched on the folder name (with/without full path) - no search results.
When I restart my machine, I can delete it. Not sure if down to user permissions. I see from this that Users only have Read/write not full control. (sorry - not very good with user permissions stuff - especially on windows!). However - surely it can't be this as I can delete it upon restart.
The folder is on a non OS drive.
I'm stumped - any ideas?
A folder cannot be deleted on Windows if any application uses this folder currently as working directory.
In your case I suppose that the batch file uses command cd to change the working directory to the created directory. So you need to use cd once again to set a different working directory before using command rmdir to delete this directory.
It is of course no good idea to start other applications with working directory being currently the directory which should be deleted later and which continue running on exit of batch file as those started applications have this directory as working directory as well.
I had same issue, after launched a powershell process from a folder via win cmd.
After powershell finished, I cd .. in win CMD but rd /q /s gave error: open in another process
I get same error when manually delete folder in explorer window, even if it was empty.
wmic process revealed that powershell.exe could be locking the folder, even though powershell had finished the task & powershell window had closed.
This was confirmed by tasklist
I then taskkill /im powershell.exe, after which the folder could be deleted.
My word - that was an obscure one, but finally found the answer by stepping through the code putting the rmdir in various places. I post this here in case anyone encounters the same...
Basically, I was calling cmd prompts and launching external exe's whilst in the said folder. Later, I was forcibly closing the exe's with TaskKill, but this was leaving the cmd consoles open at the path of the directory I was trying to delete. I'll try be clearer....
Whilst batch script was in the directory (e.g. C:\Windows\Scripts\Launch), I used the following command:
Start "AppLaunch" Call "!_supExe!" !_supCmd!
Which, after expansion, translated to, for e.g.:
Start "AppLaunch" Call "C:\Windows\Program Files(x86)\Troubleshooter\trbshtr.exe" -game "My Game"
I was using this because, from reading, there appears to be a bug in windows making the following command fail:
Start "AppLaunch" "C:\Windows\Program Files(x86)\Troubleshooter\trbshtr.exe" -game "My Game"
The problem comes when you have to use quotes for both the exe and the parameters (for instance where there's spaces). Windows doesn't read it right. Thus had to use topmost to launch these apps.
Problem being, when used:
taskkill /f /im trbshtr.exe
The exe was killed, but the command prompt wasn't. Using /b on the Start command made no difference.
So, the solution was - cd out of the directory into one that the batch script doesn't alter before launching the other apps via the above. Job done....
Now that just leaves me with how to close all those opened cmd windows (or those in taskmgr if I use the /b switch). That's probably a topic for another search or thread!
I`m trying to code a batch file that checks whether a file exists in my c drive.
If it exists , it will end the batch file.
if not, it will run an MSI file.
I got it to run the MSI file , however after installing it.
The checks do not work and it keeps prompting me to install the file.
I have attached the code that i have written.
And also is there any way to do a slient install of MSI in batch?
May i know what is wrong with the code?
if exist "C:\Program Files (x86)\Common Files\hi.txt" goto END
msiexec /i "\\computer-name\Test\setup.msi"
:END
You could do the silent install by typing >nul after msiexec /i "\\computer-name\Test\setup.msi"
So, it would look like this:
msiexec /i "\\computer-name\Test\setup.msi">nul
This works on my computer, I hope it works for you too :)
I am having some trouble creating a batch file, I need it to remove a .msi file first and then run a .exe file this is what I have so far.
echo on
title remove mimecast 3.5.6
if exist c:\windows\mimecastrem.tag goto alldone
msiexec.exe /x {86C4653D-E9B2-4421-8578-D2B953FFAEDA} /qn /L "C:\windows\mimecast.log"
start \\fcmsvr2\MimecastMSO\deploymimecast.exe /zap
echo. >c:\windows\mimecastrem.tag
:alldone
rem exit
If I run this in DOS logged on the pc it runs ok, I have tried to add this to a GPO startup and shutdown and the batch runs but only removes the .msi file and won't start the .exe, is there a way to add logging to this so I can see why it isn't running?
Thanks
David
Create a Wrapper Script to Capture the Output
When I try to run batch commands from a GPO, I usually have two batch files:
One batch file does all the work.
One to call the other and redirect all the output.
This way, if the important batch file has syntax problems (usually due to the contents of variables or other conditions on the machine), I still see something in the log.
batch_worker.cmd
#ECHO OFF
SETLOCAL
#ECHO Proceeding with important tasks...
REM do other stuff (delete, install, etc.)
batch_wrapper.cmd
CALL %~dp0batch_worker.cmd > C:\Windows\TEMP\batch_worker.log 2>&1
Self-Wrapping
Another option that I occasionally employ is to have the script invoke itself, redirecting the output.
batch_worker.cmd
#ECHO OFF
SETLOCAL
IF NOT "%_LOGGING%"=="1" (
SET _LOGGING=1
CALL "%0" %* > C:\Windows\TEMP\batch_worker.log 2>&1
EXIT /B %ERRORLEVEL%
)
#ECHO Proceeding with important tasks...
REM do other stuff (delete, install, etc.)
Network Files from GPO
Any startup scripts that run on a Windows machine will have the network identity of the computer account (COMPUTERNAME$). This account doesn't usually have access to most network resources. The one exception is the GPO. All computer accounts have access to the GPO (which is stored as files).
If your script needs other files:
Store them in a world-readable network location (or grant any domain member RX access).
Store them with the GPO.
When you create/add a startup script, the GPMC snap-in gives you access to the network location (under SYSVOL) where the script should reside. Use that UNC path to save any other files the script needs access to.