How to hide Windows 7 updates in batch, based on KB number? - batch-processing

Hy,
I'm interested to find a way (maybe vbs script?) to hide several (more than 10, anyway) windows 7 updates, so they never get installed.
I think the best way would be if I could parse a .txt file where I have each KB number listed (each on new line). But of course, if it makes the code simpler, an array hardcoded inside the script would work as well. The only requirement would be to go by KB number and not by description.
The problem is that I have no idea how I should do this and therefore I am asking help from you guys.
Thank you very much!

You can definitely do this with a VBS script. Similar questions have already been answered on some of the other StackExchange sites (see How to disable the “Get Windows 10” icon shown in the notification area (tray)? and also Block specific Windows update hotfix)
The parts that are relevant to your question are copied below. The original questions are worth reading, and they have additional notes that might also be helpful.
These were written specifically to deal with the GWX updates, but you can use any KB number with them.
"BlockWindows10.bat":
ECHO OFF
REM --- remember to invoke from ELEVATED command prompt!
REM --- or start the batch with context menu "run as admin".
SETLOCAL
REM --- (as of 2015-09-07):
REM KB3035583 - GWX Update installs Get Windows 10 app in Windows 8.1 and Windows 7 SP1
REM KB3021917 - Update to Windows 7 SP1 for performance improvements
REM KB3012973 - Upgrade to Windows 10 Pro
REM --- no longer blocking:
REM KB2952664 - Compatibility update for upgrading Windows 7
REM KB2976978 - Compatibility update for Windows 8.1 and Windows 8
REM KB3022345 - Telemetry [Replaced by KB3068708]
REM KB3068708 - Update for customer experience and diagnostic telemetry
REM --- uninstall updates
echo uninstalling updates ...
start "title" /b /wait wusa.exe /kb:3021917 /uninstall /quiet /norestart
echo - next
start "title" /b /wait wusa.exe /kb:3035583 /uninstall /quiet /norestart
echo - done.
timeout 10
REM --- hide updates
echo hiding updates ...
start "title" /b /wait cscript.exe "%~dp0HideWindowsUpdates.vbs" 3021917 3035583 3012973
echo - done.
echo ... COMPLETED (please remember to REBOOT windows, now)
pause
REM --- EOF
"HideWindowsUpdates.vbs" (Kudo https://serverfault.com/a/341318):
'// Inspired by Colin Bowern: https://serverfault.com/a/341318
If Wscript.Arguments.Count < 1 Then
WScript.Echo "Syntax: HideWindowsUpdates.vbs [KB1] [KB2] ..." & vbCRLF & _
" - Example1: HideWindowsUpdates.vbs 3035583" & vbCRLF & _
" - Example2: HideWindowsUpdates.vbs 3035583 3012973"
WScript.Quit 1
End If
Dim objArgs
Set objArgs = Wscript.Arguments
Dim updateSession, updateSearcher
Set updateSession = CreateObject("Microsoft.Update.Session")
Set updateSearcher = updateSession.CreateUpdateSearcher()
Wscript.Stdout.Write "Searching for pending updates..."
Dim searchResult
Set searchResult = updateSearcher.Search("IsInstalled=0")
Dim update, kbArticleId, index, index2
WScript.Echo CStr(searchResult.Updates.Count) & " found."
For index = 0 To searchResult.Updates.Count - 1
Set update = searchResult.Updates.Item(index)
For index2 = 0 To update.KBArticleIDs.Count - 1
kbArticleId = update.KBArticleIDs(index2)
For Each hotfixId in objArgs
If kbArticleId = hotfixId Then
If update.IsHidden = False Then
WScript.Echo "Hiding update: " & update.Title
update.IsHidden = True
Else
WScript.Echo "Already hiddn: " & update.Title
End If
End If
Next
Next
Next
'// EOF

Thank you for the help. In the meantime I was able to put together my script. Is imperfect, it may have bugs, but I ran it on my Windows 7 Pro x64 and it behaved as expected.
For anyone interested, please feel free to check it up here: https://github.com/dereius/WindowsUpdateHider

Related

Command line to kill Adobe Reader process only if it was not already running

I am trying some cmd.exe coding for the first time. I created a registry key, which contains a command called by a custom protocol handler­. What I'm trying to accomplish : Call Adobe Reader which will automatically print a pdf to a given printer. This part already works. I'm using powershell to download the pdf locally from a URL. I also want to kill the Acrobat process once i'm done, but only if it was already opened BEFORE calling my command, so I don't kill the process if the user already has a pdf opened when calling the protocol handler via Chrome.
Excuse the more than ugly formatting, a one-line command is a must in my case, I can't make a batch file or .ps1 file.
cmd /V /C set exists="0" & (tasklist | find "AcroRd32.exe" > nul) & if
(%%ERRORLEVEL%%==0 set exists="1") & set myvar=%1 & call set
myvar=%%myvar:ie:=%% & call set printer=%%myvar:*###=%% & call set
printer=^"%%printer%%^" & call set printer=%%printer:'=%% & call start
powershell.exe -ExecutionPolicy Bypass -Command $url=%%myvar%%; $pdf =
$url.split('#'); md -Force c:\TempPdf "| Out-Null"; (New-Object
System.Net.WebClient).DownloadFile($pdf,'C:/TempPdf/PatientLabel.pdf'); &
timeout /t 2 & call start acrord32.exe /n /t C:/TempPdf/PatientLabel.pdf
%%printer%% & timeout /t 2 & (if !exists!=="1" taskkill /f /im acrord32.exe)
The part which does not work is the tasklist/taskkill. I want to set the %%exists%% variable to 1 if I can find the process running before starting AcroRd32.exe and kill it after printing if %%exists%%=1. I think this might just not be working because of the execution time/parse, but I don't really know how to use /V and !var! anyway. The exists and ERRORLEVEL variables don't seem to expand.
Thanks for the help !

Execute .bat file vb.net

I need to install my win service. With installUtil it is just few lines of code.
#ECHO OFF
REM The following directory is for .NET 2.0
set DOTNETFX2=%SystemRoot%\Microsoft.NET\Framework\v2.0.50727
set PATH=%PATH%;%DOTNETFX2%
echo Installing MyService...
echo ---------------------------------------------------
InstallUtil /i MyService.exe
echo ---------------------------------------------------
echo Done.
pause
But my thoughts are without creating .bat file and then runing it.
Is there any way i can ".execute" those lines of code above without creating .bat file runing it and then deleting it ?.
I will need to dynamically create this code every time because i need to enter the username/password depending what user entered on .net form.
You could start cmd and doing it in one line via it's arguments:
Process.Start("cmd.exe", "/k set DOTNETFX2=%SystemRoot%\Microsoft.NET\Framework\v2.0.50727 & set PATH=%PATH%;%DOTNETFX2% & InstallUtil /i MyService.exe")
And if you want it to show the text you wrote and to "pause" (stay open):
Process.Start("cmd.exe", "/k set DOTNETFX2=%SystemRoot%\Microsoft.NET\Framework\v2.0.50727 & set PATH=%PATH%;%DOTNETFX2% & echo Installing MyService... & echo --------------------------------------------------- & InstallUtil /i MyService.exe & echo --------------------------------------------------- & echo Done. & pause")
Commands are separated by " & ".
I know it's been a month since you first asked this, but I recently came up with a pretty good solution to this - only using this simple VB.NET code:
Public Sub InstallService(ByVal ServicePath As String)
Dim InstallUtilPath As String = IO.Path.Combine(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(), "installutil.exe")
Dim InstallUtilProcess As Process = Process.Start(InstallUtilPath, """" & ServicePath & """")
InstallUtilProcess.WaitForExit()
'Service is now installed.
InstallUtilProcess = Process.Start(InstallUtilPath, "/i """ & ServicePath & """")
InstallUtilProcess.WaitForExit()
'The second action is now done. Show a MessageBox or something if you'd like.
End Sub
The ServicePath parameter is the path to the service that you want to install.
The InstallUtilPath variable will be set to the path of the installutil.exe application. It will get the path for the current framework you're running.
As I'm running .NET Framework 4 the path is C:\Windows\Microsoft.NET\Framework\v4.0.30319\installutil.exe
Hope this helps!

Delete application executable on exit

So I am trying to get my application to delete itself on exit.
I am currently using this (found here):
Process.Start("cmd.exe",
"/C choice /C Y /N /D Y /T 3 & Del " + Application.ExecutablePath);
Application.Exit();
The CMD window comes up, but will not remove the application. Any ideas why not?
EDIT:
So it works sometimes... other times it does not... ideas?
I think the problem is that you cannot delete an application while it's running.
You could introduce some delay in the cmd command(I don't know how), or you could simply make another application with a timer set on 5 sec. And insert the code:
System.IO.File.Delete(Application.ExecutablePath)
Me.Close
Then just use the Process.Start("your/Delete/App/Path.exe") in the first app.

Is it possible to return error code to VBA from batch file?

My batch file:
SET username=%1
SET password=%2
net use "\\gessel\toys\name" %password% /user:shops\%username%
ECHO.%ERRORLEVEL%
:copy
Xcopy "\\gessel\toys\name\babytoys" "%appdata%\shops" /S /E
ECHO.%ERRORLEVEL%
IF ERRORLEVEL 0 goto disconnect
goto end
:disconnect
net use "\\gessel\toys\name\babytoys" /delete
goto end
:end
EXIT /B %ERRORLEVEL%
I have called above batch file from VBA and the code as follows:
call Shell(Environ$("COMSPEC") & " /c " & path & username & password, vbHide)
The above code is works fine. But I need to validate whether the files are copied or not in the VBA. Suppose the customer entered his username and password wrongly then he won't get the toys info. Then I have to display a message box that display message as "entered information wrong". So for that I have tried the code like this:
sub submit_click
Dim as error as integer
error = Shell(Environ$("COMSPEC") & " /c " & path & username & password, vbHide)
if error <> 0
MsgBox "Provided info wrong", vbOKOnly, "Failure"
end if
end sub
But the above code does not work. It always returns the value even the username and password is correct. But if I run the batch file it correctly returns value such as for correct details 0 and for wrong data is 2 or 4. Please anyone help me to capture error code from batch file and to pass it into VBA.
The value of ERRORLEVEL variable changes with each command execution (more or less). So as the code in your batch file is executing, each command generates a change. You need to store the value for later processing or, in your case, exit with the adecuated value in each of the steps:
SET "username=%~1"
SET "password=%~2"
rem This will be tested for a errorlevel value of 1 or greater. In this case,
rem no further processing will be done if errors found, so we return our own
rem value to the calling process
net use "\\gessel\toys\name" %password% /user:shops\%username%
if errorlevel 1 exit /b 100
rem We are connected, and will disconnect no matter if xcopy worked or failed
rem So, the result of the command will be stored to later return the adecuate value
Xcopy "\\gessel\toys\name\babytoys" "%appdata%\shops" /S /E
set "exitCode=%errorlevel%"
net use "\\gessel\toys\name\babytoys" /delete
EXIT /B %exitCode%
Now, in the vba code the error variable can be tested for value 100 (what we returned from errors in net use) or for any of the values returned from xcopy.
Now that we have a working batch file, let's to to Excel.
NO, Shell function in VBA can not do what you are asking. The return value of Shell is the id of the running process. Shell do not wait for the process to end, so, it can not return its exit code.
BUT, the WshShell object can do what you need.
Dim oSHELL, batchFile, user, password, exitCode
Set oSHELL = VBA.CreateObject("WScript.Shell")
batchFile="myBatchFile.cmd"
user="myUserName"
password="this is my password"
' Quote strings to avoid problems with spaces
' The arguments are WhatToRun, WindowStyle (0=hide), WaitForProcessToEnd
exitCode = oSHELL.Run(""""+batchFile+""" """+user+""" """+password+"""", 0, True)

How to delete my old program file?

So how can I delete a old file once it's updated? I'm making a program were once it's updated to delete the old version. I don't have a installer so I wouldn't know the location of the file. How can I delete it after it's updated and I don't know were the user put the file that I need to delete? I've searched and everything that shows up you need to have the path.
You could use ClickOnce as suggested, but if you really don't want to use any "external" tools.. this might do the job:
Sorry for my coding, i use this snipet in some of my projects aswell and it works quite good.
This is used in the application that is being updated...
fileupdatepath = "The path to your file which is the updated one you downloaded."
Dim pi As New ProcessStartInfo("cmd.exe", String.Format("/c ping 1.1.1.1 -n 1 -w 15000 >NUL & move /y {0} {1} & start {1}", fileupdatedpath, Application.ExecutablePath)) With {.CreateNoWindow = True, .UseShellExecute = False}
Process.Start(pi)
Application.Exit()
This waits 15s to ensure the current application is closed properly before starting the new one, this is used if the same name and application path needs to be kept, as the move command is being used to replace any files with the same name., if not you can just start the new one, close the current, and delete the current application file...
Note: 'This works if the application path has no special characters like '#' or ' '
In the above answer, you can put quotes around the fileupdatepath and application.executablepath and the code will work even if if there is a space in the file locations. The final code will look like this:
fileupdatepath = "The path to your file which is the updated one you downloaded."
Dim pi As New ProcessStartInfo("cmd.exe", String.Format("/c ping 1.1.1.1 -n 1 -w 15000 >NUL & move /y {0} {1} & start {1}", """" & fileupdatedpath& """", """" & Application.ExecutablePath & """")) With {.CreateNoWindow = True, .UseShellExecute = False}
Process.Start(pi)
Application.Exit()