Add new network location, not map network drive - vb.net

Let's say I have 100 users and I need to add several network locations for each user. They cannot be network drives (e.g. Q:) as some users already have more than 26 drives mapped.
I was hoping to do this using either a batch file or a VB script. I've managed to get it working using a VB script by adding network shortcuts but this isn't the solution the users need.
I've been searching and can't find anything related specifically to Network Locations.
I'm open to trying other methods.

EDITED to properly answer the question; the original answer, that creates a shortcut in Network Locations, is kept at the end.
After some testing, a network location is a read-only folder located in the %AppData%\Microsoft\Windows\Network Shortcuts folder, with two files inside: desktop.ini with a precise content (see in code) and a target.lnk shortcut to the target.
Option Explicit
Function CreateNetworkLocation( networkLocationName, networkLocationTarget )
Const ssfNETHOOD = &H13&
Const fsATTRIBUTES_READONLY = 1
Const fsATTRIBUTES_HIDDEN = 2
Const fsATTRIBUTES_SYSTEM = 4
CreateNetworkLocation = False
' Instantiate needed components
Dim fso, shell, shellApplication
Set fso = WScript.CreateObject("Scripting.FileSystemObject")
Set shell = WScript.CreateObject("WScript.Shell")
Set shellApplication = WScript.CreateObject("Shell.Application")
' Locate where NetworkLocations are stored
Dim nethoodFolderPath, networkLocationFolder, networkLocationFolderPath
nethoodFolderPath = shellApplication.Namespace( ssfNETHOOD ).Self.Path
' Create the folder for our NetworkLocation and set its attributes
networkLocationFolderPath = fso.BuildPath( nethoodFolderPath, networkLocationName )
If fso.FolderExists( networkLocationFolderPath ) Then
Exit Function
End If
Set networkLocationFolder = fso.CreateFolder( networkLocationFolderPath )
networkLocationFolder.Attributes = fsATTRIBUTES_READONLY
' Write the desktop.ini inside our NetworkLocation folder and change its attributes
Dim desktopINIFilePath
desktopINIFilePath = fso.BuildPath( networkLocationFolderPath, "desktop.ini" )
With fso.CreateTextFile(desktopINIFilePath)
.Write "[.ShellClassInfo]" & vbCrlf & _
"CLSID2={0AFACED1-E828-11D1-9187-B532F1E9575D}" & vbCrlf & _
"Flags=2" & vbCrlf
.Close
End With
With fso.GetFile( desktopINIFilePath )
.Attributes = fsATTRIBUTES_HIDDEN + fsATTRIBUTES_SYSTEM
End With
' Create the shortcut to the target of our NetworkLocation
Dim targetLink
targetLink = fso.BuildPath( networkLocationFolderPath, "target.lnk" )
With shell.CreateShortcut( targetLink )
.TargetPath = networkLocationTarget
.Save
End With
' Done
CreateNetworkLocation = True
End Function
CreateNetworkLocation "Tests", "\\192.168.1.2\c$"
Tested in Windows 7.
Original answer - Just in case someone finds it useful.
All you need to do is to create a shortcut in the folder:
%AppData%\Microsoft\Windows\Network Shortcuts
Just a VBScript sample (as indicated in the question, not sure if the tags points to another needs):
Option Explicit
Const ssfNETHOOD = &H13&
Dim fso, shell, shellApplication
Set fso = WScript.CreateObject("Scripting.FileSystemObject")
Set shell = WScript.CreateObject("WSCript.Shell")
Set shellApplication = WScript.CreateObject("Shell.Application")
Dim networkLocationsFolder
networkLocationsFolder = shellApplication.Namespace( ssfNETHOOD ).Self.Path
With shell.CreateShortcut(fso.BuildPath( networkLocationsFolder, "Test PC.lnk" ))
.TargetPath = "\\192.168.1.10\c$"
.WindowStyle = 1
.IconLocation = "shell32.dll, 9"
.Description = "Access to Test computer drive"
.WorkingDirectory = "\\192.168.1.10\c$"
.Save
End With

Related

where are the windows users names stored in xp...?

I am writing an application that searches for a particular file in the C:\Documents and Settings\user accounts\Application Data folder. Now i am trying to make this application generic. I can make this application search in a particular users application data folder. But what i am tryin to do is take the user name from a certain file or place where windows xp stores it. Then make it search for that user. Is there a particular way to do it.
Need ideas and suggestions.
User Names are Stored in Windows Registry or Use Can get FolderNames as C:\Documents and Settings contains Every Folder with a UserName
The problem here is that Microsoft has not provided an API method of doing this directly. Perhaps it was an oversight. That being said, any solution you find is going to be some kind of workaround and is going to present some kind of limitations.
Using the registry to get this information is not officially supported by Microsoft and thus, may not work going forward.
Iterating through user profile folders is unreliable because the folder is not always named after its user and because you can change its location.
And so on.
All of that being said, I use a combination of WMI and the registry to accomplish this. Here's what it looks like in VBScript, you should be able to adapt it to your needs.
' Create some arrays to hold the data.
arrUsers = Array()
arrSIDs = Array()
arrAppDataFolders = Array()
' Get a list of all the non-system users with their SID
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2"
Set colUsers = objWMIService.ExecQuery _
("Select * from Win32_UserAccount Where Status = 'OK'")
i = 0
For Each objUser in colUsers
ReDim Preserve arrUsers(i)
ReDim Preserve arrSIDs(i)
arrUsers(i) = objUser.Name
arrSIDs(i) = objUser.SID
i = i + 1
Next
Set colUsers = Nothing
Set objWMIService = Nothing
' Now go to the registry and get the Document folder location using the SID
Const HKEY_USERS = &H80000003
Set objRegistry = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\default:StdRegProv")
ReDim arrAppDataFolders(UBound(arrSIDs))
For i = 0 to UBound(arrSIDs)
strKeyPath = arrSIDs(i) & "\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
strValueName = "AppData" ' or "Local AppData"
intReturn = objRegistry.GetExpandedStringValue HKEY_USERS, strKeyPath, strValueName, strValue
If (intReturn = 0) And (Err.Number = 0) Then
arrAppDataFolders(i) = strValue
Else
arrAppDataFolders(i) = vbNull
End If
Next
Set objRegistry = Nothing
net user
from a command prompt will return a list of all users... probably more than what you're asking for. Your best bet is to do what you had already planned on doing with your Documents and Settings.

VB.Net: How To Display Previous Shadow Copy Versions of File Allowing User to Choose One

I'm writing an Excel file recovery program with VB.Net that tries to be a convenient place to gather and access Microsoft's recommended methods. If your interested in my probably kludgy, error filled, and lacking enough cleanup code it's here: http://pastebin.com/v4GgDteY. The basic functionality seems to work although I haven't tested graph macro table recovery yet.
It occurred to me that Vista and Windows 7 users could benefit from being offered a list of previous versions of the file within my application if the Shadow Copy Service is on and there are previous copies. How do I do this?
I looked at a lot of web pages but found no easy to crib code. One possibility I guess would be to use vssadmin via the shell but that is pretty cumbersome. I just want to display a dialogue box like the Previous Versions property sheet and allow users to pick one of the previous versions. I guess I could just display the previous version property sheet via the shell by programmatically invoking the context menu and the "Restore previous versions choice", however I also want to be able to offer the list for Vista Home Basic and Premium Users who don't have access to that tab even though apparently the previous versions still exist. Additionally if it possible I would like to offer XP users the same functionality although I'm pretty sure with XP only the System files are in the shadow copies.
I looked at MSDN on the Shadow Copy Service and went through all the pages, I also looked at AlphaVSS and AlphaFS and all the comments. I'm kind of guessing that I need to use AlphaVss and AlphFS and do the following?
Find out the list of snapshots/restore points that exist on the computer.
Mount those snapshots.
Navigate in the mounted volumes to the Excel file the user wants to recover and make a list of those paths.
With the list of paths handy, compare with some kind of diff program, the shadow copies of the files with the original.
Pull out the youngest or oldest version (I don't think it matters) of those shadow copies that differ from the recovery target.
List those versions of the files that are found to be different.
This seems cumbersome and slow, but maybe is the fastest way to do things. I just need some confirmation that is the way to go now.
I finally decided to go ahead and start coding. Please make suggestions for speeding up the code or what do with files that are found to be different from the recovery file target. Is there a simpler way to do this with AlphaVSS and AlphaFS?
Private Sub Button1_Click_2(sender As System.Object, e As System.EventArgs) Handles Button1.Click
'Find out the number of vss shadow snapshots (restore
'points). All shadows apparently have a linkable path
'\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy#,
'where # is a simple one, two or three digit integer.
Dim objProcess As New Process()
objProcess.StartInfo.UseShellExecute = False
objProcess.StartInfo.RedirectStandardOutput = True
objProcess.StartInfo.CreateNoWindow = True
objProcess.StartInfo.RedirectStandardError = True
objProcess.StartInfo.FileName() = "vssadmin"
objProcess.StartInfo.Arguments() = "List Shadows"
objProcess.Start()
Dim burp As String = objProcess.StandardOutput.ReadToEnd
Dim strError As String = objProcess.StandardError.ReadToEnd()
objProcess.WaitForExit()
Dim xnum As Integer = 0
Dim counterVariable As Integer = 1
' Call Regex.Matches method.
Dim matches As MatchCollection = Regex.Matches(burp, _
"HarddiskVolumeShadowCopy")
' Loop over matches.
For Each m As Match In matches
xnum = xnum + 1
'At the max xnum + 1 is the number of shadows that exist
Next
objProcess.Close()
Do
'Here we make symbolic links to all the shadows, one at a time
'and loop through until all shadows are exposed as folders in C:\.
Dim myProcess As New Process()
myProcess.StartInfo.FileName = "cmd.exe"
myProcess.StartInfo.UseShellExecute = False
myProcess.StartInfo.RedirectStandardInput = True
myProcess.StartInfo.RedirectStandardOutput = True
myProcess.StartInfo.CreateNoWindow = True
myProcess.Start()
Dim myStreamWriter As StreamWriter = myProcess.StandardInput
myStreamWriter.WriteLine("mklink /d C:\shadow" & counterVariable _
& " \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy" _
& counterVariable & "\")
myStreamWriter.Close()
myProcess.WaitForExit()
myProcess.Close()
' Here I compare our recovery target file against the shadow copies
Dim sFile As String = PathTb.Text
Dim sFileShadowPath As String = "C:\shadow" & _
counterVariable & DelFromLeft("C:", sFile)
Dim jingle As New Process()
jingle.StartInfo.FileName = "cmd.exe"
jingle.StartInfo.UseShellExecute = False
jingle.StartInfo.RedirectStandardInput = True
jingle.StartInfo.RedirectStandardOutput = True
jingle.StartInfo.CreateNoWindow = True
jingle.Start()
Dim jingleWriter As StreamWriter = jingle.StandardInput
jingleWriter.WriteLine("fc """ & sFile & """ """ _
& sFileShadowPath & """")
jingleWriter.Close()
jingle.WaitForExit()
Dim jingleReader As StreamReader = jingle.StandardOutput
Dim JingleCompOut As String = jingleReader.ReadToEnd
jingleReader.Close()
jingle.WaitForExit()
jingle.Close()
Dim jingleBoolean As Boolean = JingleCompOut.Contains( _
"no differences encountered").ToString
If jingleBoolean = "True" Then
MsgBox(jingleBoolean)
Else
'I haven't decided what to do with the paths of
'files that are different from the recovery target.
MsgBox("No")
End If
counterVariable = counterVariable + 1
Loop Until counterVariable = xnum + 1
End Sub

AutoUpdate VBA startup macro?

I'm building some Word 2003 macro that have to be put in the %APPDATA%\Microsoft\Word\Startup folder.
I can't change the location of this folder (to a network share). How can I auto update this macros ?
I have tried to create a bootstrapper macro, with an AutoExec sub that copy newer version from a file share to this folder. But as Word is locking the file, I get a Denied Exception.
Any idea ?
FYI, I wrote this code. The code is working fine for update templates in templates directory, but not in startup directory :
' Bootstrapper module
Option Explicit
Sub AutoExec()
Update
End Sub
Sub Update()
MirrorDirectory MyPath.MyAppTemplatesPath, MyPath.WordTemplatesPath
MirrorDirectory MyPath.MyAppStartupTemplatesPath, MyPath.WordTemplatesStartupPath
End Sub
' IOUtilities Module
Option Explicit
Dim fso As New Scripting.FileSystemObject
Public Sub MirrorDirectory(sourceDir As String, targetDir As String)
Dim result As FoundFiles
Dim s As Variant
sourceDir = RemoveTrailingBackslash(sourceDir)
targetDir = RemoveTrailingBackslash(targetDir)
With Application.FileSearch
.NewSearch
.FileType = MsoFileType.msoFileTypeAllFiles
.LookIn = sourceDir
.SearchSubFolders = True
.Execute
Set result = .FoundFiles
End With
For Each s In result
Dim relativePath As String
relativePath = Mid(s, Len(sourceDir) + 1)
Dim targetPath As String
targetPath = targetDir + relativePath
CopyIfNewer CStr(s), targetPath
Next s
End Sub
Public Function RemoveTrailingBackslash(s As String)
If Right(s, 1) = "\" Then
RemoveTrailingBackslash = Left(s, Len(s) - 1)
Else
RemoveTrailingBackslash = s
End If
End Function
Public Sub CopyIfNewer(source As String, target As String)
Dim shouldCopy As Boolean
shouldCopy = False
If Not fso.FileExists(target) Then
shouldCopy = True
ElseIf FileDateTime(source) > FileDateTime(target) Then
shouldCopy = True
End If
If (shouldCopy) Then
If Not fso.FolderExists(fso.GetParentFolderName(target)) Then fso.CreateFolder (fso.GetParentFolderName(target))
fso.CopyFile source, target, True
Debug.Print "File copied : " + source + " to " + target
Else
Debug.Print "File not copied : " + source + " to " + target
End If
End Sub
' MyPath module
Property Get WordTemplatesStartupPath()
WordTemplatesStartupPath = "Path To Application Data\Microsoft\Word\STARTUP"
End Property
Property Get WordTemplatesPath()
WordTemplatesPath = "Path To Application Data\Microsoft\Templates\Myapp\"
End Property
Property Get MyAppTemplatesPath()
MyAppTemplatesPath = "p:\MyShare\templates"
End Property
Property Get XRefStartupTemplatesPath()
MyAppStartupTemplatesPath = "p:\MyShare\startup"
End Property
[Edit] I explored another way
Another way I'm thinking about, is to pilot the organizer :
Sub Macro1()
'
' Macro1 Macro
' Macro recorded 10/7/2011 by beauge
'
Application.OrganizerCopy source:="P:\MyShare\Startup\myapp_bootstrapper.dot", _
Destination:= _
"PathToApplication Data\Microsoft\Word\STARTUP\myapp_bootstrapper.dot" _
, Name:="MyModule", Object:=wdOrganizerObjectProjectItems
End Sub
This is working, but has limitations :
either I have to hard-code modules to organize
or I have to change the option "Trust VBA project" to autodiscover items like this (which is not acceptable as it requires to lower the security of the station) :
the code of the project enumeration is this one :
Public Sub EnumProjectItem()
Dim sourceProject As Document
Dim targetProject As Document
Set sourceProject = Application.Documents.Open("P:\MyShare\Startup\myapp_bootstrapper.dot", , , , , , , , , wdOpenFormatTemplate)
Set targetProject = Application.Documents.Open("PathToApplication Data\Microsoft\Word\STARTUP\myapp_bootstrapper.dot", , , , , , , , , wdOpenFormatTemplate)
Dim vbc As VBcomponent
For Each vbc In sourceProject.VBProject.VBComponents 'crash here
Application.ActiveDocument.Range.InsertAfter (vbc.Name + " / " + vbc.Type)
Application.ActiveDocument.Paragraphs.Add
Next vbc
End Sub
[Edit 2] Another unsuccessful try :
I put, in my network share, a .dot with all the logic.
In my STARTUP folder, I put a simple .Dot file, that references the former one, with a single "Call MyApp.MySub".
This is actually working, but as the target template is not in a trusted location, a security warning is popped up each time word is launched (even if not related to the current application macro)
At least, I succeed partially using these steps :
Create a setup package. I use a NSIS script
the package detect any instance of Winword.exe and ask the user to retry when word is closed
extract from the registry the word's option path
deploy the files into the word's startup folder
add an uninstaller in the local user add/remove programs
I put the package in the remote share. I also added a .ini file containing the last version of the package (in the form "1.0")
In the macro itself, I have a version number ("0.9" for example).
At the startup (AutoExec macro), I compare the local version to the remote version
I use shell exec to fire the setup if a newer version is found.
The setup will wait for Word to close
A bit tricky, but it works on Word 2K3 and Word 2K10.

tool or vbscript to add hardcoded text to top of multiple files?

Does anyone know a tool that can add predefined text such as the following 4 lines:
"My disclaimer:
For legal reasons -
1. Don't blah...
2. You must..."
to all .txt files in a directory: "C:/test/"
I have seen append functions but they only add to the bottom, not sure of a method for adding to the top of the file.
My OS is Win XP.
SrcHead is a free utility that can adjust the header of multiple sourcefiles. It is written for Windows and needs the .NET Framework 2.0 to work.
Haven't tested this, but it should put you on the right track.
Dim FSO, txs, fld, fil, content
Set FSO = CreateObject("Scripting.FileSystemObject")
Set fld = FSO.GetFolder("C:\test\")
For Each fil In fld.Files
If Right(fil.Name, 3) = "txt" Then
Set txs = fil.OpenAsTextStream(1) ' 1 = for reading
content = txs.ReadAll
txs.Close
Set txs = fil.OpenAsTextStream(2) ' 2 = for writing
txs.Write "MyDisclaimer:" & vbCrLf & "stuff" & content
txs.Close
End If
Next

Use a variable in file path in .vbs

Is it possible to usa variable in a path in .vbs. My basic situation is I have a vbs script that will often be run on a computer with one person logged in and run by an admin with a completely different user name (assume the file will be right clicked and "Run As").
The script edits an ini file that is located in the user directory for the person logged in. I know in batch I could simply insert the variable "C:\Users\%Logger%\AppData\Local\stat.ini" and the variable would be replaced. But I can't do this in .vbs. My script thus far. Or look at the bulk of it in an answer here.
Dim blnRes: blnRes = 0
Dim strOld, strNew, logger
strOld = "frogg"
strNew = "frog"
logger = Inputbox("What is your Domain ID exactly as entered when you log into this machine?","Domain ID")
On Error Resume Next
Call update("C:\Users\logger\AppData\Local\stat.ini", strOld, strNew)
blnRes = blnRes Or (Err.Number = 0): Err.Clear
Is there some way I can flag logger as a variable, or is there an easier way to do this?
I guess you meant a script variable. Try this:
logger = Inputbox("What is ID?","Domain ID")
Call update("C:\Users\"& logger &"\AppData\Local\stat.ini", strOld, strNew)
You can use command line arguments with vbs. See the following technet site:
http://technet.microsoft.com/en-us/library/ee156618.aspx
using the example vbs at the bottom, you can have Ping.vbs reply based on the computer name entered after the script name when its called (C:\scripts\Ping.vbs Hostname)
Here's more info on WScript.Aurguments
https://www.google.com/search?q=WScript.Arguments&sourceid=ie7&rls=com.microsoft:en-us:IE-Address&ie=&oe=
'Ping.vbs:
Dim arArguments, strArgument
Set arArguments = WScript.Arguments
WScript.Echo WScript.Arguments.Count
For Each strArgument in arArguments
If Ping(strArgument) Then
WScript.Echo strArgument & " is available."
Else
WScript.Echo strArgument & " is not available."
End If
Next
Function Ping( myHostName )
Dim colPingResults, objPingResult, strQuery
strQuery = "SELECT * FROM Win32_PingStatus WHERE Address = '" & myHostName & "'"
Set colPingResults = GetObject("winmgmts://./root/cimv2").ExecQuery( strQuery )
For Each objPingResult In colPingResults
If Not IsObject( objPingResult ) Then
Ping = False
ElseIf objPingResult.StatusCode = 0 Then
Ping = True
Else
Ping = False
End If
Next
Set colPingResults = Nothing
End Function
If I understand what you're after correctly, you're either going to need to do a string concatenation where you build a string like "string part 1" & logger & "string part 2" or use the replace function to replace %Logger% (e.g. Replace(templateString, "%Logger%", logger)) with your logger variable. There's not a direct equivalent to the %1 sort of format used in batch files.
This worked for me:
Dim fs, ws, Path
Set ws = CreateObject( "WScript.Shell" )
Path = ws.ExpandEnvironmentStrings( "%UserProfile%\testfile.txt" )
ws = Nothing
Set fs = CreateObject("Scripting.FileSystemObject")
Set f = fs.CreateTextFile (Path, True)
f.WriteLine("This is a test")
f.Close()
f = Nothing
Don't assume "C:\Users" will be valid on every system. There are times when you may want to use a different location for user profiles. I also looked at the %AppData% environment variable, but in my case that pointed to AppData\Roaming, and you want AppData\Local.