Install/Uninstall MSI Application based upon domain group membership

This script will help you install a particular application based upon user membership in a particular domain group. Installmsiapp will check the computer's installed (MSI) applications, see if it can find the requested software title, then install the app if it is missing, and if the logged in user is a member of the requested domain group (no nested groups currently)

Note that this is for MSI-packaged applications ONLY.

Also, the enumeration of all MSI packages currently installed can take a little while to process.
---------------------------------------------------------------------------------------------

The script will take the following inputs as command-line parameters:

* title: the application title of the MSI (i.e. "Microsoft .NET Framework 1.1") - this can be found in add/remove programs if you wanted to see exact text of title.

* path: the path of the installation MSI (i.e. "\\fileserver\share\netfx.msi)

* group: the name of the domain group (i.e. "Install - .NET")

* uninstallifnotmember: uninstall if the logged on user is not a member of the group (i.e. "yes"|"no")

* install: tell the script to install or uninstall an application ("install"|"uninstall") - you may want to uninstall if a person is a member of a group.

Note: the group must be a domain group of the currently logged in user domain. Also, the name must match EXACTLY (case-insensitive). If the user is not a member of the specified group, the script will exit without checking to see if the application is installed or not. This allows for faster processing.

If the requested application is not installed, a popup dialog will appear, telling the user that the application needs to be installed and to please wait (this will disappear after 10 seconds (default)).

When the msi installs, it will use the /passive msiexec.exe command-line switch, which only shows a progress bar, but no other intervention is necessary.

When the installation finishes, there will be a logfile in the user's %temp% folder called 'vbsmsi_install-status.log', resulting from the script execution (not directly related to the MSI installation).

This script is particularly useful for deploying applications via the logon script, but you don't want to go the route of deploying via GPO (or if perhaps the GPO isn't working properly with a third-party MSI).

So, in this case, you would create a user group on the domain level called 'Install - .Net 1.1', add users to it, then assign the batch file containing the above code to those users...or, you can deploy a GPO with this as a logon script, then only give Install - .Net 1.1' permissions to apply it through the security filtering tab...then assign the GPO to the domain.

Source Code

This script has not been checked by Spiceworks. Please understand the risks before using it.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

onerrorresumenext'http://community.spiceworks.com''Author: 'Rob Dunn ''Email Address: 'uphold2001@hotmail.com''Script Name: 'installmsiapp.vbs ''Script Version: '2.1''Description:'This script will help you install a particular application based upon user' membership in a particular domain group. Installmsiapp will check the' computer's installed (MSI) applications, see if it can find the requested' software title, then install the app if it is missing, and if the logged' in user is a member of the requested domain group (no nested groups currently)''Note that this is for MSI-packaged applications ONLY.''The script will take three inputs as command-line parameters:''title: the application title of the MSI (i.e. "Microsoft .NET Framework 1.1")'path: the path of the installation MSI (i.e. "\\fileserver\share\netfx.msi)'group: the name of the domain group (i.e. "Install - .NET")'uninstallifnotmember: uninstall if the logged on user is not a member of the group (i.e. "yes"|"no")'install: tell the script to install or uninstall an application ("install"|"uninstall")''Note: the group must be a domain group of the currently logged in user domain.' Also, the name must match EXACTLY (case-insensitive). If the user is not ' a member of the specified group, the script will exit without checking to see' if the application is installed or not. This allows for faster processing.''If the requested application is not installed, a popup dialog will' appear, telling the user that the application needs to be installed and ' to please wait (this will disappear after 10 seconds (default)).''When the msi installs, it will use the /passive msiexec.exe command-line ' switch, which only shows a progress bar, but no other intervention is ' necessary.''This script is particularly useful for deploying applications via the logon' script, but you don't want to go the route of deploying via GPO (or if ' perhaps the GPO isn't working properly with a third-party MSI).''An example of this being called from a batch file login script:''cscript.exe /nologo "%logonserver%\netlogon\vbs\installmsiapp.vbs" title:"Microsoft .NET Framework 1.1" path:"\\server\public\dotnet1.1\netfx.msi" group:"Install - .NET 1.1" action:"install" uninstallifnotmember:"false"''So, in this case, you would create a user group on the domain level called' 'Install - .Net 1.1', add users to it, then assign the batch file containing' the above code to those users...or, you can deploy a GPO with this as a ' logon script, then only give 'Install - .Net 1.1' permissions to apply it' through the security filtering tab...then assign the GPO to the domain.'Declare a couple of constants for our WMI connection string (courtesy of ' the Microsoft Scriptomatic 2.0 tool).ConstwbemFlagReturnImmediately=&h10ConstwbemFlagForwardOnly=&h20ConstForWriting=2SetWshShell=WScript.CreateObject("WScript.Shell")SetWshSysEnv=WshShell.Environment("PROCESS")Setfso=wscript.CreateObject("Scripting.FileSystemObject")DimstrAction,strForce,bMember,strTitle,logfile,l,blnCscriptIfInStr(ucase(WScript.FullName),"CSCRIPT.EXE")ThenblnCScript=TRUEElseblnCScript=FALSEEndIflogfile=wshShell.ExpandEnvironmentStrings("%temp%")&"\VBSMSI_Install-status.log"OnErrorresumenext'Declare objectsSetobjArgs=WScript.Arguments'Declare variablesdimbInstalled,objWMIService'Set to 'false' since we are assuming NOT installed, we will check later...' Do NOT modify.bInstalled=false'If you don't want this script installing anything on servers, set this to ' 'true' - set to 'false' if you don't care. :)bDontRunOnServers=true'Show variables as they are being passed, status, etc. - ' 0 = No debug, perform installation' 1 = Debug, show variables, no installation (don't run MSI at end of script)iDebug=0'wscript.echo vbnewlineSetl=fso.OpenTextFile(logfile,ForWriting,True)'Get command-line argumentsIfobjargs.count<1Then'If no command line parameters are passed, exit the script.strMsg="You must specify a title, path, and groupname as command-line parameters in order for this script to function."ifblnCScript=Truethenwscript.echostrMsgcallwritelog(strMsg)wscript.quitElse'Go through all the command-line options and find out what was passed.ForI=0toobjArgs.Count-1callwritelog("Command line parameter: "&objargs(i))'Find the title of the application we are looking for.IfInStr(1,LCase(objargs(I)),"title:")ThenarrTitle=split(objargs(I),"title:")strTitle=replace(arrTitle(1),"'","")ifidebug=1thenwscript.echo"Title: "&strTitleElseIfInStr(1,LCase(objargs(I)),"path:")Then'Find the path of the application down to the .msi extension for the title' we were shown above.arrPath=split(lcase(objargs(I)),"path:")strPath=replace(arrPath(1),"'","")ifidebug=1thenwscript.echo"Path: "&strPathElseIfInStr(1,LCase(objargs(I)),"group:")Then'What domain group does this user (who is running the script) need to belong' to in order for the .msi to run?arrGroup=split(objargs(I),"group:")strGroup=replace(arrGroup(1),"'","")ifidebug=1thenwscript.echo"Group: "&strGroupElseIfInStr(1,LCase(objargs(I)),"action:")Then'Find the path of the application down to the .msi extension for the title' we were shown above.arrAction=split(lcase(objargs(I)),"action:")strAction=replace(arrAction(1),"'","")ifidebug=1thenwscript.echo"Action: "&strPathElseIfInStr(1,LCase(objargs(I)),"uninstallifnotmember:")Then'Do we want to uninstall this application if the user is not a member of ' the requested group?.arrForce=split(lcase(objargs(I)),"uninstallifnotmember:")strForce=replace(arrForce(1),"'","")ifidebug=1thenwscript.echo"UninstallIfNotMember: "&strForceElseEndIfIfstrForce=""andstrAction=""andstrGroup=""andstrPath=""andstrTitle=""thenstrMsg="You must specify all command-line switches (title|path|group|action|uninstallifnotmember). Aborting script execution."wscript.echostrmsgcallwritelog(strMsg)wscript.quitEndIfNextEndIfSubWritelog(strMsg)l.writeline("["&Now&"] "&strMsg)EndSub'When strComputer = ".", then that means tell the script to check the computer' which is running the script (local).strComputer="."'Create WMI connection to computer.SetobjWMIService=GetObject("winmgmts:\\"&strComputer&"\root\cimv2")'Find the OS version from the PC running the script.SetcolOperatingSystems=objWMIService.ExecQuery("Select Caption from Win32_OperatingSystem")ForEachobjOperatingSystemincolOperatingSystems'If there's an error, then abort the script rather than continue.Iferr.number<>0thencallwritelog("An error occured. Error #"&err.number&", "&err.description)EndIf'If this script has been specified to NOT run on servers, then abort.IfbDontRunOnServers=trueThenIfInStr(objOperatingSystem.Caption,"Server")orInStr(objOperatingSystem.Caption,"Powered")ThenstrMsg="This script ("&wscript.scriptname&") is configured to run on workstations only."wscript.echostrMsgcallwritelog(strMsg)wscript.quitEndIfEndIfNext'Find out if the currently logged on user is a member of the group we specified' in strGroup above. If the user is not a member, then quit the script.bMember=isMember(strGroup)'If the user is not a member of the group, and we want to force an uninstall' using the strForce switch, then set the script action to "uninstall"IfbMember=falseandstrForce="yes"thenifblnCScript=Truethenwscript.echo"Configuration set to uninstall if "&strTitle&" exists"strAction="uninstall"'If the user is not a member of the group, but we don't care if the user keeps' the application on their system, abort the script.ElseIfbMember=falseandstrForce="no"thenifblnCScript=Truethenwscript.echo"Leaving "&strTitle&" intact"wscript.quitEndIfIfiDebug=1thenwscript.echo"Action: "&strAction&" application"'Show text - - if run with cscript.exe, this will show up in the console window' for the logon script. If not, it will show up in a pop-up window.ifblnCScript=Truethenwscript.echo"Verifying install status for "&strTitle&". Please stand by..."Ifidebug=1thenwscript.echo"Is a member of "&strGroup&": "&IsMember(strGroup)'Find out if the application we specified is installed - - - i.e. call the ' function that checks the status.CallCheckInstalledStatusl.closearrFile=split(strPath,"\")onerrorresumenextSetf=fso.GetFile(wshShell.ExpandEnvironmentStrings("%temp%")&"\"&replace(lcase(arrFile(ubound(arrFile)))&"_install-status.log",".msi",""))' Delete the previous logfilef.Delete'Move the file to a new filename (more appropriately named).onerrorresumenextfso.MoveFilelogfile,wshShell.ExpandEnvironmentStrings("%temp%")&"\"&replace(lcase(arrFile(ubound(arrFile))),".msi","")&"_Install-status.log"'******************************************************************************'Function CheckInstalledStatus''Determines if the application is installed or not, and install or uninstall' depending on whether we specified to force an uninstallation based upon ' group membership (i.e. if user is not a member, uninstall the app if strForce' was set to 'yes').'******************************************************************************FunctionCheckInstalledStatusonerrorresumenext'Perform a WQL (Windows Query Language) query through the WMI connection' above, and output the results to a collection called 'colItems'.SetcolItems=objWMIService.ExecQuery("SELECT Caption FROM Win32_Product where caption='"&strTitle&"'","WQL",wbemFlagReturnImmediately+wbemFlagForwardOnly)Iferr.number=80041062thenstrMsg="An error has occured: Error #"&err.number&", "&err.description&". You do not have sufficient privileges on this computer to enumerate installed applications."ifblnCScript=Truethenwscript.echovbnewlineifblnCScript=Truethenwscript.echostrMsgcallwritelog(strMsg)ifblnCScript=Truethenwscript.echovbnewlinewscript.quitEndIf'Move through each item in the collection.ForEachobjItemIncolItems'If one of the captions has the text that we specified for the title (i.e.' strTitle, then we know the application is installed.Ifinstr(objItem.Caption,strTitle)thenifblnCScript=Truethenwscript.echoobjItem.Caption&" is installed. Continuing script."ifblnCScript=Truethenwscript.echovbnewline'Set this variable to 'true' so we can reference it later.bInstalled=trueEndIfNext'If the application is not installed, then install the application...IfbInstalled=falseorstrAction="uninstall"thenSetWshShell=WScript.CreateObject("WScript.Shell")'Give the user a warning telling them what is going on. This will ' disappear after 10 seconds.ifstrAction="install"thenstrMsg="Your userid or computer has been approved to install "&strTitle&". Now installing '"&strTitle&"', please stand by, this may take a few minutes..."&vbcrlf&vbcrlf&"This message will disappear in 10 seconds"WshShell.PopupstrMsg,10,"Software installation in progress",64callwritelog(strMsg)'Set the installation command line we are going to run, using the path we ' specified in strPath above. Use the /passive switch so that the user' will only see the progress bar during installation.sCmd="msiexec.exe /i "&chr(34)&strPath&chr(34)&" /passive"strMsg="Installing "&strTitleifblnCScript=Truethenwscript.echostrMsgcallwritelog(strMsg)'Give the user a warning telling them what is going on. This will ' disappear after 10 seconds.ElseIfstrAction="uninstall"andstrForce="yes"andbInstalled="true"thenstrMsg="Your userid has NOT been approved for "&strTitle&". Now uninstalling '"&strTitle&"', please stand by, this may take a few minutes..."&vbcrlf&vbcrlf&"This message will disappear in 10 seconds"WshShell.PopupstrMsg,10,"Software uninstallation in progress",64callwritelog(strMsg)'Set the uninstall command line we are going to run, using the path we ' specified in strPath above. Use the /passive switch so that the user ' will only see the progress bar during installation.sCmd="msiexec.exe /uninstall "&chr(34)&strPath&chr(34)&" /passive"strMsg="Uninstalling "&strTitleifblnCScript=Truethenwscript.echostrMsgcallwritelog(strMsg)'If the user is not a member of the group, the script switched to' uninstall. If we don't care if they have it installed, then exit the' function.ElseIfbInstalled<>"true"ThenifblnCScript=Truethenwscript.echostrTitle&" is not installed. Script will exit."CallWriteLog(strTitle&" is not installed. Script will exit.")ifblnCScript=Truethenwscript.echovbnewlineElseIfstrAction="uninstall"andstrForce="no"thenExitFunctionEndIfifsCmd<>""thencallwritelog("Command line: "&sCmd)ifidebug=1thenwscript.echo"Command: "&sCmdifidebug<>1thenwshshell.runsCmd,1,trueElse'If the application is installed, then show a quick blurb in the console' window.strMsg=strTitle&" is already installed on this computer. Script will exit."ifidebug=1thenwscript.echostrmsgcallwritelog(strMsg)EndIfEndFunction'*******************************************************************************'*******************************************************************************'Function IsMember(groupName)''Input: Title of group name you wish to query against. This will check the ' domain and logged on user ID to find out whether or not it is a member of the ' specified group in 'strGroup' - the title must match the group name exactly.'*******************************************************************************PrivateFunctionIsMember(groupName)SetobjADInfo=CreateObject("ADSystemInfo")'Try to pick up computer domain via AD'strComputerDomain=objADInfo.DomainShortName'Instantiate the network objectSetnetObj=CreateObject("WScript.Network")'Set variable sDomain to the logged on user's domain.sDomain=netObj.UserDomainifsDomain=""ThensDomain=strComputerDomainstrMsg="No user domain found, defaulting to computer domain: "&sDomainElsestrMsg="Found domain: "&sDomainEndIfcallwritelog(strMsg)'Set variable sUser to the logged on user's ID.sUser=netObj.UserNameifsUser<>""andlcase(sUser)<>"system"thenstrMsg="Found user: "&sUserelsesUser=netObj.Computername&"$"strMsg="No username found, defaulting to computername: "&sUserendifcallwritelog(strMsg)'Set is member to false, as if there any problems we want to err on the side' of caution (don't install if we don't know he/she is a member)flgIsMember=false'Attach to the user object in the domain using the WinNT provider.SetuserObj=GetObject("WinNT://"&sDomain&"/"&sUser&",user")'Move through each group that this user is a member of.ForEachgrpInuserObj.Groups'if blnCScript = True then wscript.echo grp.namewritelog("Member of: "&grp.Name)'If the name of one of the user's groups match the one we specified then' the user is a member...i.e. flgIsMember = true.Iflcase(grp.Name)=groupNameThenflgIsMember=true'Don't keep searching, so exit the 'for' loop.ExitForEndIfNext'IsMember will equal 'true'/'false', depending on what the code above found.IsMember=flgIsMemberstrMsg="("&strTitle&") - Group membership to ["&sDomain&"\"&groupName&"]: "&IsMemberifblnCScript=Truethenwscript.echostrMsgCallwritelog(strMsg)'Set declared objects to nothing to free up memory.SetuserObj=nothingSetnetObj=nothingEndFunction'*******************************************************************************

I can modify the code to allow you to utilize your own switches, but can you elaborate on the second question? Do you want it to install/uninstall if a domain user is a member of a group on the local computer?

A daily dose of today's top tech news, in brief.
You need to hear this.
Reddit gets native video support
Variety reports that Reddit has just introduced a new feature that allows you to upload video clips directly to the service. The feature was ...

For a long time we have been happily using the Dell E Dock. But as Dell are removing the E dock port I need to find a good USB docking station. What is everyone else using? We are a nonprofit so need something cheap.

I am curious about what others think when having to take an exam to qualify for a position. I personally don't feel that a company can really judge a person just by taking a test for a position the company is hiring for. Now I know they are trying to see if this individual is qualified, but sometimes there are questions on these exams that even experts can't answer.