Forum Discussion
KevinA
16 years agoRetired GoTo Contributor
One2Many Script Repository
Welcome to the LogMeIn Central Script Repository!
What is it? A library of scripts to help you execute automated tasks and manage LogMeIn Pro² computers without having to access them manually.
How does it work? Simply browse the .txt files below, save as a .BAT file and head to your LogMeIn Central console. Then, navigate to the One2Many tab, and select "Run a batch file or executable." From there, simply upload the batch file and you're ready to go.
How can you help? We encourage you to share your own scripts and/or help review the scripts of others-- just "Kudo" your favorites or reply with your comments.
Use of these scripts is at your own risk so please test them on a small number of systems before deploying at scale. The scripts are provided “as is” without any warranty of any kind and LogMeIn disclaims any and all liability regarding any use of the scripts. Please see the following Terms and Conditions for more information.
Remember: The currently running One2Many script ends when either the host service stops or the script includes computer shutdown or reboot tasks.
Script Repository
Microsoft Updates
Windows Update Javascript- The following script will perform comprehensive Windows Updates (Windows and Microsoft updates) on remote computers. This java script must be run as a Custom Task within One2Many with cscript being the entry point, Command to execute to update and install in the Custom Task is:
cscript.exe "%LMI_PACKAGEROOT%\wu.js" /sa /i
/sa will find updates that are flagged to be automatically selected by Windows Update. This is critical to avoid installing all available updates for the computer as this may include over ten 500Mb language support files on Vista and Win7. /i is the command argument that instructs the script to download and install the updates found. Additional arguments are outlined within the source code of the JavaScript.
Both the script and the command to execute can be customized to suite your environment’s needs.
Security
Disable Firewall- disable the Microsoft Windows Firewall for the appropriate version of Windows.
Enable Firewall- enable the Microsoft Windows Firewall for the appropriate version of Windows.
Install AVI Convert- install the LogMeIn Rescue AVI Converter which converts LogMeIn Rescue .rcec
recordings to .avi, for the appropriate version of Windows.
Update AVG Virus Definitions: Updates your AVG (versions 8 and/or 9) virus definition files
Maintenance
Purge DLL Cache- delete and restore the cache folder associated with Microsoft System File Checker for the appropriate version of Windows.
Reboot- reboot the remote device(s) with an end-user notification for the appropriate version of Windows. Remember: When a host is restarted, it disconnects from Central and the currently running One2Many script stops. Since One2Many cannot continue script execution, rebooting a device should be the last step of your One2Many script as it ends the script.
Shut down-shut down the remote device(s) immediately for the appropriate version of Windows. Remember: When a host is shut down, it disconnects from Central and the currently running One2Many script stops. Since One2Many cannot continue script execution, shutting down a device should be the last step of your One2Many script as it ends the script.
Reset System Restore- reset (disable/enable) Microsoft System Restore for the appropriate version of
windows.
Turn Off System Restore- disable Microsoft System Restore for the appropriate version of windows.
Turn On System Restore- enable Microsoft System Restore for the appropriate version of windows.
Defrag- Defragments C volume
Spool Cleaner- Cleans print spooler (submitted by iDevelop)
LogMeIn Update- Updates host software with the latest version of LogMeIn.
Use of these scripts is at your own risk so please test them on a small number of systems before deploying at scale. The scripts are provided “as is” without any warranty of any kind and LogMeIn disclaims any and all liability regarding any use of the scripts. Please see the following Terms and Conditions for more information.
(edited and updated 2/23/23 by GlennD)
https://github.com/knix15/LogMeIn-One2Many-Community-Scripts/
Scripts can be found here as well for better future organization.
136 Replies
Replies have been turned off for this discussion
- Colorado_Al11 years agoActive Contributor
Thanks.
I was thinking msiexec unistall command too, but can't find the registry string.
I tried a bat file like this:
cd "C:\Program Files (x86)\LogMeIn\x64\"
logmein uninstall
It removes it from your LMI Central account, and on the PC it does not auto run, but the installer is still resident in "Programs and Features" and the LogMeIn service still runs.
- joelasaro11 years agoActive Contributor
Lol. It really shouldn't be that tough to do the uninstall, though I confess I haven't tried it. Basically, you would write a batch file to do the unistall. I would probably try an msiexec unistall command or maybe wmic. The trick I think would jut be to use One2Many to write this as a .com file and then use the start command to kick it off like the upgrade script previously discussed in this thread.
- Colorado_Al11 years agoActive Contributor
Can anyone suggest a way to use one2many to silently uninstall LogMeIn?
- englanddg12 years agoNew Contributor
Ok, I went back and checked a bunch of clients where I was NOT logged in with an active profile through Logmein (unlike the tests) after running the job, and it seems to have worked. I didn't audit the entire network, but I'll say, THANKS for the script. I think this will do EXACTLY what I wanted!
- englanddg12 years agoNew ContributorWell, the first two client tests it prompted me (but I was also remoted into the machine to see the desktop, so maybe that's it)...
I may have spoken too soon, as when I logged into other machines after pushing it out to a larger group (a few dozen machines) AFTER the job finished, I didn't see any interaction prompts.
I may have just applied it incorrectly, so I'll keep playing with it. If I find something (including me being silly) I'll post details, until then, just disregard my post. - joelasaro12 years agoActive ContributorEnglanddg -
What user interaction did you run into? For me it was pretty seamless. The /s with the raupdate.exe command should run it silently.
I have been having trouble getting the latest update that just came out to install. No errors just doesn't seem to be available for all my nodes yet. But I'll need to test more to be sure of what the issue is and it did work for a couple of machines so far. - englanddg12 years agoNew Contributor
This is great, and it worked fine on my clients...however, it does require user interaction. Something I'd rather avoid.
Considering the way Logmein is going, automatic update and install for the LMI client really should be a feature, or at least a job that can be done without user interaction.
Am I missing something?
- joelasaro12 years agoActive Contributor
The issue with not being able to update the LMI client from One2Many or any built-in function is especially bad when there is a bug in version 4634 that causes high cpu usage constantly (svchost.exe process) and there is no way to automatically force clients to update.
I have automatic updates enabled for all the LMI Pro clients and still have about a third of them on 4634 instead of 4670.***Update:
I finally got to test the batch script for updating LMI and it seems to be working fine for me. I used a condensed version of the script linked in the first post of this topic that I found on spiceworks:
http://community.spiceworks.com/scripts/show/2544-logmein-silent-update-heartbleed-counter
I just saved this as a .bat file and uploaded into a One2Many "Run a batch file or executable" type script. When I run this the machine goes offline after a bit and stays offline for a few minutes and then comes backonline one LMI is updated. I have successfull update two machines so far this way with no issues. I upgraded from version 4634 to 4670.
Obviously, this functionality should be backed into LMI Central, but this is atleast usable in my experience so far. Below is the script from the SpiceWorks post that I used.
@echo off cd %TEMP% if %PROCESSOR_ARCHITECTURE% equ AMD64 goto amd64 echo cd "%ProgramFiles%\logmein\x86\update" > lmiupdate.cmd goto x86done :amd64 echo cd "%ProgramFiles(x86)%\logmein\x64\update" > lmiupdate.cmd :x86done echo raupdate.exe /s >> lmiupdate.cmd echo exit >> lmiupdate.cmd REM Now it'll run it start lmiupdate.cmd
- cbr00t12 years agoNew Contributor
Hi all,
I want to share a downloader&installer code that I used with LMI Tasks.
Program is a Non-Interactive File Downloader & Installer tool in .NET C# works on Windows systems.
This program is calling by a LogMeIn One2Many Task like this:
Batch Type: Batch or Exe
Program : CNIPackageInstallerApp.exe
Parameters : -of cnioutput.xml -dl ftp:!!user:pass@ftp.mydownloadserver.com!public!mypackage!MyProgramSetup.Ver1.3.exe,c:#lmidownloads#_MYPROGRAM.EXE -il c:#lmidownloads#_MYPROGRAMSETUP.EXE,!silent
This code is so useful for LMI Tasks. It works as Non-Interactive. All inputs are given from commandline and it writes operation output into given output xml file. If operation success program returns 0 as exitcode, and other if fails.
I use this code to deploy & update/install my products to our customers.
Program doesn't need an user interaction and GUI system.
Works fine on Windows XP and later that installed MS .NET Framework 4.0.
Code can be developed for other languages like Java, C++ ... etc and other systems.
Here is program codes (2 class):
Kernel.cs
using System; using System.Collections.Generic; using System.Linq; using System.Windows.Forms; using System.Text; using System.Reflection; using System.Net; using System.Net.Sockets; using System.IO; using System.Diagnostics; using System.Threading; public static class Kernel { public const char Delim_ArgSeperator = ';' , Delim_SubArgSeperator = ','; public const string ResultSection_Download = "Download" , ResultSection_Install = "Install"; public static string[] startupArgs; static bool runStatus; static Exception lastError; static TimeSpan beginTime, endTime; static CDict<string, CDict<string, string>> section2OutputDict; static FileInfo outputFile; static List<KeyValuePair<string, string>> downloadURLsAndTargets, installFilesAndArguments; #region Kernel Startup /// <summary>The main entry point for the application</summary> [STAThread] static int Main( string[] args ) { int exitCode; try { Application.EnableVisualStyles(); } catch { } try { Application.SetCompatibleTextRenderingDefault( false ); } catch { } startupArgs = new string[0]; if (args != null && args.Length > 1) { startupArgs = new string[args.Length]; for (var i = 0; i < startupArgs.Length; i++) startupArgs[i] = args[i].Replace( '!', '/' ).Replace( '#', '\\' ).Replace( '?', ' ' ); //startupArgs = new string[args.Length - 1]; //Array.Copy( args, 1, startupArgs, 0, startupArgs.Length ); } initializeGlobals(); beginTime = DateTime.Now.TimeOfDay; try { exitCode = run( args ); } catch (Exception ex) { exitCode = handleFatalError( ex ); } endTime = DateTime.Now.TimeOfDay; dumpOutput(); return exitCode; } public static int run( string[] args ) { loadConfig(); initializeStartup(); if (downloadURLsAndTargets.Count > 0) downloadFiles(); if (installFilesAndArguments.Count > 0) installFiles(); return ( runStatus ? 0 : 2 ); } #endregion #region Islem static void downloadFiles() { const int BufferSize = 1024 * 256 , MaxTryCount = 3 , ErrorWaitTimeMS = 1500; foreach (var kv in downloadURLsAndTargets) { int tryCount = -1; string url; FileInfo targetFile; WebRequest req = null; Stream webSrm = null, fileSrm = null; WebResponse resp = null; byte[] buffer = null; int bytes; redownload: tryCount++; url = kv.Key; targetFile = new FileInfo( kv.Value ); try { req = WebRequest.Create( url ); } catch (Exception ex) { try { req.Abort(); } catch { } if (tryCount < MaxTryCount) { Thread.Sleep( ErrorWaitTimeMS ); goto redownload; } runStatus = false; outputDownloadResult( url, "connect_fail " + ex.Message ); continue; } try { if (req is FtpWebRequest) { ( (FtpWebRequest)req ).Method = WebRequestMethods.Ftp.DownloadFile; ( (FtpWebRequest)req ).UsePassive = true; ( (FtpWebRequest)req ).UseBinary = true; } else if (req is HttpWebRequest) { ( (HttpWebRequest)req ).Method = WebRequestMethods.Http.Get; } else { try { req.Abort(); } catch { } if (tryCount < MaxTryCount) { Thread.Sleep( ErrorWaitTimeMS ); goto redownload; } runStatus = false; outputDownloadResult( url, "invalid_protocol" ); continue; }
try { resp = req.GetResponse(); webSrm = resp.GetResponseStream(); } catch (Exception ex) { try { req.Abort(); } catch { } if (tryCount < MaxTryCount) { Thread.Sleep( ErrorWaitTimeMS ); goto redownload; } runStatus = false; outputDownloadResult( url, "response_read_error " + ex.Message ); continue; } if (!targetFile.Directory.Exists) { targetFile.Directory.Create(); targetFile.Refresh(); } fileSrm = targetFile.Open( FileMode.Create, FileAccess.ReadWrite, FileShare.Read ); buffer = new byte[BufferSize]; try { while (( bytes = webSrm.Read( buffer, 0, buffer.Length ) ) > 0) fileSrm.Write( buffer, 0, bytes ); } catch (Exception ex) { try { req.Abort(); } catch { } if (fileSrm != null) fileSrm.Close(); targetFile.Refresh(); if (targetFile.Exists) { targetFile.Delete(); targetFile.Refresh(); } //if (ex is WebException && ( (WebException)ex ).Status == WebExceptionStatus.UnknownError) { if (tryCount < MaxTryCount) { Thread.Sleep( ErrorWaitTimeMS ); goto redownload; } runStatus = false; outputDownloadResult( url, "download_error " + ex.Message ); continue; } outputDownloadResult( url, "success" ); } finally { if (buffer != null) { Array.Resize( ref buffer, 1 ); buffer = null; } if (fileSrm != null) fileSrm.Close(); if (webSrm != null) webSrm.Close(); if (resp != null) resp.Close(); if (req != null) { try { req.Abort(); } catch { } } } } } static void installFiles() { foreach (var kv in installFilesAndArguments) { FileInfo file; string args; ProcessStartInfo psi; Process pr; file = new FileInfo( kv.Key ); args = kv.Value; if (!file.Exists) { runStatus = false; outputInstallResult( file.FullName, "file_notfound" ); continue; } psi = new ProcessStartInfo( file.FullName, args ); psi.UseShellExecute = false; psi.CreateNoWindow = true; if (( pr = Process.Start( psi ) ) == null) { runStatus = false; outputInstallResult( file.FullName, "processstart_failed" ); continue; } pr.WaitForExit(); outputInstallResult( file.FullName, "success_exitcode " + pr.ExitCode.ToString() ); } } #endregion #region Error Handler public static int handleFatalError( Exception ex ) { setLastError( ex ); return 99; } #endregion #region Std I/O static void dumpOutput() { StringBuilder sb; string outputData; FileStream srm; sb = new StringBuilder(); writeXMLOutputDataTo( new StringWriter( sb ) ); outputData = sb.ToString(); if (runStatus) Console.Out.Write( outputData ); else Console.Error.Write( outputData ); if (outputFile != null) { if (outputFile.Exists) { outputFile.Delete(); outputFile.Refresh(); } File.WriteAllText( outputFile.FullName, outputData, Encoding.Default ); } } static void writeXMLOutputDataTo( TextWriter sw ) { Exception currentError; currentError = lastError; if (currentError != null && currentError.InnerException != null) currentError = currentError.InnerException; sw.WriteLine( string.Format( @"<?xml version=""1.0"" encoding=""{0}"" ?>", Encoding.Default.BodyName ) ); sw.WriteLine( @"<RunResult>" ); sw.WriteLine( string.Format( @" <RunStatus>{0}</RunStatus>", runStatus ? "success" : "fail" ) ); sw.WriteLine( @" <SystemInfo>" ); sw.WriteLine( string.Format( @" <MachineName>{0}</MachineName>", Environment.MachineName ) ); sw.WriteLine( string.Format( @" <DomainName>{0}</DomainName>", Environment.UserDomainName ) ); sw.WriteLine( string.Format( @" <UserName>{0}</UserName>", Environment.UserName ) ); sw.WriteLine( string.Format( @" <IsInteractiveMode>{0}</IsInteractiveMode>", Environment.UserInteractive.ToString() ) ); sw.WriteLine( string.Format( @" <OSBits>{0}</OSBits>", ( Environment.Is64BitOperatingSystem ? "x64" : "x86" ) ) ); sw.WriteLine( string.Format( @" <ProcessorBits>{0}</ProcessorBits>", ( Environment.Is64BitProcess ? "x64" : "x86" ) ) ); sw.WriteLine( string.Format( @" <ProcessorCount>{0}</ProcessorCount>", Environment.ProcessorCount.ToString() ) ); sw.WriteLine( string.Format( @" <ProcessCommandLine>{0}</ProcessCommandLine>", Environment.CommandLine ) ); sw.WriteLine( @" </SystemInfo>" ); sw.WriteLine( @" <Duration>" ); sw.WriteLine( string.Format( @" <BeginTime>{0}</BeginTime>", beginTime.ToString() ) ); sw.WriteLine( string.Format( @" <EndTime>{0}</EndTime>", endTime.ToString() ) ); sw.WriteLine( string.Format( @" <TotalSeconds>{0}</TotalSeconds>", ( endTime - beginTime ).ToString() ) ); sw.WriteLine( @" </Duration>" ); if (lastError == null) sw.WriteLine( @" <LastError />" ); else { sw.WriteLine( @" <LastError>" ); sw.WriteLine( string.Format( @" <Class>{0}</Class>", currentError.GetType().Name ) ); sw.WriteLine( string.Format( @" <Message>{0}</Message>", currentError.Message ) ); if (currentError is WebException) sw.WriteLine( string.Format( @" <Status>{0}</Status>", ( (WebException)currentError ).Status.ToString() ) ); else if (currentError is SocketException) sw.WriteLine( string.Format( @" <Status>{0}</Status>", ( (SocketException)currentError ).SocketErrorCode.ToString() ) ); else sw.WriteLine( @" <Status />" ); sw.WriteLine( string.Format( @" <StackTrace>{0}</StackTrace>", currentError.StackTrace ) ); sw.WriteLine( @" </LastError>" ); } sw.WriteLine( @" <Outputs>" ); primitiveWriteXMLOutputStringResult( sw, ResultSection_Download ); primitiveWriteXMLOutputStringResult( sw, ResultSection_Install ); sw.WriteLine( @" </Outputs>" ); sw.WriteLine( @"</RunResult>" ); sw.Flush(); } static void outputDownloadResult( string key, string value ) { primitiveOutputSuccessResult( ResultSection_Download, key, value ); } static void outputInstallResult( string key, string value ) { primitiveOutputSuccessResult( ResultSection_Install, key, value ); } static void setLastError( Exception ex ) { runStatus = false; lastError = ex; } static void primitiveWriteXMLOutputStringResult( TextWriter sw, string section ) { if (!section2OutputDict.ContainsKey( section ) || section2OutputDict[section].IsEmpty) sw.WriteLine( string.Format( @" <{0} />", section ) ); else { sw.WriteLine( string.Format( @" <{0}>", section ) ); foreach (var kv in section2OutputDict[section]) sw.WriteLine( string.Format( @" <item ref=""{0}"">{1}</item>", kv.Key, kv.Value ) ); sw.WriteLine( string.Format( @" </{0}>", section ) ); } } static void primitiveOutputSuccessResult( string section, string key, string value ) { section2OutputDict[section][key] = value; } #endregion #region Initialize static void initializeGlobals() { runStatus = true; lastError = null; section2OutputDict = new CDict<string, CDict<string, string>>(); foreach (var attr in new[] { ResultSection_Download, ResultSection_Install }) section2OutputDict[attr] = new CDict<string, string>(); } static void loadConfig() { string temp; outputFile = null; //downloadMode = ""; downloadURLsAndTargets = new List<KeyValuePair<string, string>>(); installFilesAndArguments = new List<KeyValuePair<string, string>>(); //if (( temp = scanArgValue( "-dm" ) ) != null) { // if (new[] { "", DownloadMode_FTP, DownloadMode_HTTP }.Contains( temp )) // downloadMode = temp; // else // throw new ArgumentOutOfRangeException( temp ?? "", "invalidstartuparg -dm" ); //} if (( temp = scanArgValue( "-of" ) ) != null) { outputFile = new FileInfo( temp ); } if (( temp = scanArgValue( "-dl" ) ) != null) { string[] parts, subParts; downloadURLsAndTargets = new List<KeyValuePair<string, string>>(); parts = temp.Split( new char[] { Delim_ArgSeperator }, StringSplitOptions.RemoveEmptyEntries ); foreach (var part in parts) { if (string.IsNullOrWhiteSpace( part )) continue; subParts = part.Split( new char[] { Delim_SubArgSeperator }, 2 ); downloadURLsAndTargets.Add( new KeyValuePair<string, string>( subParts[0], ( subParts.Length > 1 ? subParts[1] : "" ) ) ); } } if (( temp = scanArgValue( "-il" ) ) != null) { string[] parts, subParts; installFilesAndArguments = new List<KeyValuePair<string, string>>(); parts = temp.Split( new char[] { Delim_ArgSeperator }, StringSplitOptions.RemoveEmptyEntries ); foreach (var part in parts) { if (string.IsNullOrWhiteSpace( part )) continue; subParts = part.Split( new char[] { Delim_SubArgSeperator }, 2 ); installFilesAndArguments.Add( new KeyValuePair<string, string>( subParts[0], ( subParts.Length > 1 ? subParts[1] : "" ) ) ); } } } static void initializeStartup() { if (outputFile != null && !outputFile.Exists) { if (!outputFile.Directory.Exists) { outputFile.Directory.Create(); outputFile.Refresh(); } } } #endregion #region Yardimci static string scanArgValue( string arg ) { int index; string value; if (( index = Array.IndexOf( startupArgs, arg ) ) < 0) return null; return startupArgs[index + 1]; } #endregion }CDict.cs
#region Using directives using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Windows.Forms; #endregion /// <summary>Standard CDict yapısı</summary> [Serializable()] public class CDict<TKey, TValue> : Dictionary<TKey, TValue> { #region Get/Set [TypeConverter( typeof( ExpandableObjectConverter ) )] public virtual TValue this[TKey key] { get { try { return base[key]; } catch (KeyNotFoundException e) { throw new KeyNotFoundException( string.Format( "KeyNotFound: [{0}]", key ), e ); } set { if (base.ContainsKey( key )) base[key] = value; else base.Add( key, value ); } } public virtual bool IsEmpty { get { return this.Count == 0; } } #endregion public CDict() { } public CDict( params KeyValuePair<TKey, TValue>[] keyValueArray ) { this.Add( keyValueArray ); } public CDict( IEnumerable<TKey> keys, IEnumerable<TValue> values ) { this.AddRange( keys, values ); } public CDict( IDictionary<TKey, TValue> dict ) { this.AddRange( dict ); } public TValue Add( TKey key, TValue value ) { this[key] = value; return value; } public void Add( params KeyValuePair<TKey, TValue>[] keyValueArray ) { foreach (var keyValuePair in keyValueArray) this.Add( keyValuePair.Key, keyValuePair.Value ); } public CDict<TKey, TValue> AddRange( IEnumerable<TKey> _keys, IEnumerable<TValue> _values ) { var keys = new List<TKey>( _keys ); var values = new List<TValue>( _values ); if (keys != null && values != null && keys.Count == values.Count) { for (int i = 0; i < keys.Count; i++) this.Add(new KeyValuePair<TKey, TValue>(keys[i], values[i] ) ); } return this; } public CDict<TKey, TValue> AddRange( IDictionary<TKey, TValue> dict ) { foreach (var kv in dict) Add( kv ); return this; } public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() { CDict<TKey, TValue>.Enumerator dictEnum = base.GetEnumerator(); while (dictEnum.MoveNext()) yield return dictEnum.Current; } } - ilssupport12 years agoVisitor
Hello, I appologize if this has been answered already.
I deploy about 5 installations a day to different clients and would like to automate the logmein installation process. My only issue with the deployment is that I can't specify what name it should use so that the PC is named properly. I have a batch file that runs on startup that requires user input and one of those inputs would be "Do you want to install Logmein?" followed by "What should this PC be called?". This would then use the name entered in as part of a silent installer for logmein in the background. I am unable to use the hostname of the PC as I cannot enter in for example "Test SD (Test DVR# 1)" as a valid hostname.
Is this possible?
Thanks in advance for you help.