private void SetHomeLocation(string homeLocation)
        {
            if (!string.IsNullOrEmpty(homeLocation))
            {
                try
                {
                    Environment.SpecialFolder specialFolder = (Environment.SpecialFolder)Enum.Parse(typeof(Environment.SpecialFolder), homeLocation);
                    _homeLocation = new Pidl(specialFolder);
                    return;
                }
                catch (ArgumentException) {}
                catch (NotSupportedException) {}
                catch (Exception ex)
                {
                    Platform.Log(LogLevel.Debug, ex, "The special folder {0} isn't available.", homeLocation);
                }

                Pidl pidl;
                if (Pidl.TryParse(homeLocation, out pidl))
                {
                    _homeLocation = pidl;
                    return;
                }

                _homeLocation = null;
            }
        }
Example #2
0
		public ShellItem()
		{
			_rootItem = this;
			try
			{
				// create a PIDL for the Desktop shell item.
				_pidl = new Pidl(Environment.SpecialFolder.Desktop);

				var shInfo = new Native.SHFILEINFO();
				Native.Shell32.SHGetFileInfo((IntPtr) _pidl, 0, out shInfo, (uint) Marshal.SizeOf(shInfo), SHGFI.SHGFI_PIDL | SHGFI.SHGFI_DISPLAYNAME | SHGFI.SHGFI_SYSICONINDEX);

				// get the root IShellFolder interface
				int hResult = Native.Shell32.SHGetDesktopFolder(ref _shellFolder);
				if (hResult != 0)
					Marshal.ThrowExceptionForHR(hResult);

				_displayName = shInfo.szDisplayName;
				_typeName = string.Empty;
				_iconIndex = shInfo.iIcon;
				_isFolder = true;
				_isVirtual = true;
				_hasSubFolders = true;
			}
			catch (Exception ex)
			{
				// if an exception happens during construction, we must release the PIDL now (remember, it's a pointer!)
				if (_pidl != null)
					_pidl.Dispose();
				throw new Exception("Creation of the root namespace shell item failed.", ex);
			}

#if DEBUG
			_instanceCount++;
#endif
		}
Example #3
0
        public ThumbnailListItem(Pidl pidl)
        {
            if (pidl == null)
            {
                throw new System.ArgumentNullException("pidl");
            }

            InitializeIQueueItemVariables(_methodCountInternal);
            _pidl = Pidl.Create(pidl);
        }
Example #4
0
        public ThumbnailListItem(string path)
        {
            if (path == null || path.Length == 0)
            {
                throw new System.ArgumentNullException("path");
            }

            InitializeIQueueItemVariables(_methodCountInternal);
            _pidl = Pidl.Create(path);
        }
Example #5
0
        static string _ShellItemToString(api.IShellItem r)
        {
            //if(!f.Has(api.FOS.FOS_FORCEFILESYSTEM)) {
            //	var k=r.GetAttributes(0xffffffff);
            //	if(0==(k&api.SFGAO_FILESYSTEM)) {
            //		print.it(k);
            //	}
            //}

            var s = r.GetDisplayName(SIGDN.FILESYSPATH | SIGDN.URL);             //info: for a non-FS item, even with SIGDN.FILESYSPATH gets string like "::{GUID}"

            return(Pidl.ClsidToItemidlist_(s));
        }
Example #6
0
 static bool _ShellItemFromString(string path, out api.IShellItem si)
 {
     if (path.Starts(":: "))
     {
         var p = Pidl.FromString(path); if (p == null)
         {
             si = null; return(false);
         }
         return(0 == api.SHCreateItemFromIDList(p.UnsafePtr, typeof(api.IShellItem).GUID, out si));
     }
     else
     {
         return(0 == api.SHCreateItemFromParsingName(path, default, typeof(api.IShellItem).GUID, out si));
Example #7
0
        /// <summary>
        /// Initializes new instance of the ThumbnailListItem as a copy of the specified item.
        /// </summary>
        /// <param name="item">Source item.</param>
        protected ThumbnailListItem(ThumbnailListItem item)
            : base(item)
        {
            if (item == null)
            {
                throw new System.ArgumentNullException("item");
            }

            _pidl          = Pidl.Create(item._pidl);
            _kilobytesText = (string)item._kilobytesText.Clone();
            _methodCount   = item._methodCount;

            InitializeIQueueItemVariables(_methodCountInternal);
        }
        private void PerformDispose(bool disposing)
        {
            if (disposing)
            {
                // this is a managed wrapper so it should only be disposed on disposing
                if (_homeLocation != null)
                {
                    _homeLocation.Dispose();
                    _homeLocation = null;
                }

                if (_folderViewSelectionUpdatePublisher != null)
                {
                    _folderViewSelectionUpdatePublisher.Dispose();
                    _folderViewSelectionUpdatePublisher = null;
                }
            }
        }
Example #9
0
			protected override void Dispose(bool disposing)
			{
				if (disposing)
				{
					DisposeEach(this.Items);

					if (_currentShellItem != null)
					{
						_currentShellItem.Dispose();
						_currentShellItem = null;
					}

					if (_rootShellItem != null)
					{
						_rootShellItem.Dispose();
						_rootShellItem = null;
					}

					if (_myDocumentsReferencePidl != null)
					{
						_myDocumentsReferencePidl.Dispose();
						_myDocumentsReferencePidl = null;
					}
				}
				base.Dispose(disposing);
			}
Example #10
0
			public FolderListView() : base()
			{
				_currentShellItem = _rootShellItem.Clone();
				_myDocumentsReferencePidl = new Pidl(Environment.SpecialFolder.MyDocuments);

				this.Alignment = ListViewAlignment.SnapToGrid;
				this.AllowColumnReorder = false;
				this.AutoArrange = true;
				this.CheckBoxes = false;
				this.DereferenceLinks = true;
				this.HeaderStyle = ColumnHeaderStyle.Clickable;
				this.HideSelection = false;
				this.LabelEdit = false;
				this.LabelWrap = true;
				this.ListViewItemSorter = new FolderListViewItemComparer();
				this.MultiSelect = true;
				this.Scrollable = true;
				this.Sorting = SortOrder.Ascending;
				this.TileSize = new Size(12*(this.FontHeight + 4), 3*this.FontHeight + 4);
				this.View = View.LargeIcon;
				this.PopulateItems();
			}
Example #11
0
			public void Dispose()
			{
				if (_pidl != null)
				{
					_pidl.Dispose();
					_pidl = null;
				}
			}
Example #12
0
			public FolderListViewItem(Pidl absolutePidl, Pidl myDocumentsReferencePidl, FileSizeFormat fileSizeFormat)
			{
				_pidl = absolutePidl;
				_fullPath = absolutePidl.Path;

				// request shell item info now - it's faster than binding to ShellItem directly, and we need it for sorting purposes anyway
				var uFlags = SHGFI.SHGFI_PIDL | SHGFI.SHGFI_TYPENAME | SHGFI.SHGFI_DISPLAYNAME | SHGFI.SHGFI_SYSICONINDEX;

				// bug #9975: asking for SHGFI_ATTRIBUTES can be a very slow operation, so we don't want to ask for them unless we really need them.
				// if we're dealing with a regular file or directory, then getting the attributes gives us no additional information, so we can avoid it
				var isFile = !string.IsNullOrEmpty(_fullPath) && File.Exists(_fullPath);
				var isDirectory = !string.IsNullOrEmpty(_fullPath) && Directory.Exists(_fullPath);
				if (!isFile && !isDirectory)
				{
					uFlags = uFlags | SHGFI.SHGFI_ATTRIBUTES;
				}

				var shInfo = new SHFILEINFO();
				Shell32.SHGetFileInfo((IntPtr) _pidl, 0, out shInfo, (uint)Marshal.SizeOf(shInfo), uFlags);

				// check if item is purely virtual or is a physical file system object
				var isPureVirtual = !isFile && !isDirectory && ((SFGAO)shInfo.dwAttributes & SFGAO.SFGAO_FILESYSTEM) == 0;

				// check if item is actually a folder or potentially has subfolders; exclude real files that provide subfolders via shell namespace extensions (e.g. ZIP files in WinXP)
				var isFolder = isDirectory || (((SFGAO) shInfo.dwAttributes & (SFGAO.SFGAO_FOLDER | SFGAO.SFGAO_HASSUBFOLDER)) != 0 && !isFile);

				byte itemClass;
				if (_pidl == myDocumentsReferencePidl)
					itemClass = 0;
				else if (isPureVirtual && isFolder)
					itemClass = 64;
				else if (isFolder)
					itemClass = (byte) (128 + GetRootVolumeIndex(_fullPath));
				else
					itemClass = byte.MaxValue;

				this._iconIndex = shInfo.iIcon;
				this._lastModifiedValid = false;
				this.DisplayName = shInfo.szDisplayName;
				this.TypeName = shInfo.szTypeName;
				this.ItemClass = itemClass;
				this.LastModified = DateTime.MinValue;
				this.IsFolder = isFolder;
				this.FileSize = -1;

				if (File.Exists(_fullPath))
				{
					FileInfo fileInfo = new FileInfo(this._fullPath);
					this._lastModifiedValid = true;
					this.LastModified = fileInfo.LastWriteTime;
					this.FileSize = fileInfo.Length;
				}
				else if (Directory.Exists(_fullPath))
				{
					this._lastModifiedValid = true;
					this.LastModified = Directory.GetLastWriteTime(_fullPath);
				}

				this.Text = this.DisplayName;
				this.ImageIndex = this._iconIndex;
				this.SubItems.Add(CreateSubItem(this, FormatFileSize(this.FileSize, fileSizeFormat)));
				this.SubItems.Add(CreateSubItem(this, this.TypeName));
				this.SubItems.Add(CreateSubItem(this, FormatLastModified(this.LastModified, this._lastModifiedValid)));
			}
Example #13
0
			internal FolderViewItem(Pidl pidl)
				: base(pidl.Path, pidl.VirtualPath, pidl.DisplayName, pidl.IsFolder, pidl.IsLink) {}
Example #14
0
		protected override void BrowseToCore(Pidl pidl)
		{
			_folderListView.BrowseToPidl(pidl);
		}
Example #15
0
			public void BrowseTo(Pidl absolutePidl)
			{
				_suppressBrowseEvents = true;
				try
				{
					if (absolutePidl != null)
					{
						TreeNodeCollection nextSearchDomain = this.Nodes;
						do
						{
							TreeNodeCollection currentSearchDomain = nextSearchDomain;
							nextSearchDomain = null;
							foreach (FolderTreeNode node in currentSearchDomain)
							{
								if (node.Pidl == absolutePidl)
								{
									this.SelectedNode = node;
									break;
								}
								else if (node.Pidl.IsAncestorOf(absolutePidl))
								{
									node.Expand();
									nextSearchDomain = node.Nodes;
									break;
								}
							}
						} while (nextSearchDomain != null);
					}
				}
				catch (Exception ex)
				{
					HandleBrowseException(ex);
				}
				finally
				{
					_suppressBrowseEvents = false;
				}
			}
Example #16
0
		protected abstract void BrowseToCore(Pidl pidl);
Example #17
0
		protected virtual void Dispose(bool disposing)
		{
			if (!_disposed)
			{
#if DEBUG
				--_instanceCount;
#endif

				if (disposing)
				{
					if (_pidl != null)
					{
						_pidl.Dispose();
						_pidl = null;
					}

					if (_rootItem != null)
					{
						// do not dispose this - we don't own it!
						_rootItem = null;
					}
				}

				if (_shellFolder != null)
				{
					// release the IShellFolder interface of this shell item
					Marshal.ReleaseComObject(_shellFolder);
					_shellFolder = null;
				}

				_disposed = true;
			}
		}
Example #18
0
 public ThumbnailListItem(Aurigma.GraphicsMill.WinControls.StandardFolder standardFolder)
 {
     InitializeIQueueItemVariables(_methodCountInternal);
     _pidl = Pidl.Create(standardFolder);
 }
Example #19
0
		protected override void BrowseToCore(Pidl pidl)
		{
			_folderTreeView.BrowseTo(pidl);
		}
Example #20
0
			public void BrowseToPidl(Pidl pidl)
			{
				_suppressBrowseEvents = true;
				try
				{
					this.Browse(new ShellItem(pidl, _rootShellItem, false));
				}
				catch (Exception ex)
				{
					HandleBrowseException(ex);
				}
				finally
				{
					_suppressBrowseEvents = false;
				}
			}
Example #21
0
		public ShellItem(Pidl pidl, ShellItem parentShellItem) : this(pidl, parentShellItem, true) {}
Example #22
0
		public ShellItem(Pidl pidl, ShellItem parentShellItem, bool relativePidl)
		{
			int hResult;

			_rootItem = parentShellItem._rootItem;
			try
			{
				IntPtr tempPidl;
				if (relativePidl)
				{
					_pidl = new Pidl(parentShellItem.Pidl, pidl);
					tempPidl = (IntPtr) pidl; // use the relative one from parameters
				}
				else
				{
					_pidl = pidl.Clone();
					tempPidl = (IntPtr) _pidl; // use the absolute one that we constructed just now
				}

				const Native.SHGFI flags = Native.SHGFI.SHGFI_PIDL // indicates that we're specifying the item by PIDL
				                           | Native.SHGFI.SHGFI_DISPLAYNAME // indicates that we want the item's display name
				                           | Native.SHGFI.SHGFI_SYSICONINDEX // indicates that we want the item's icon's index in the system image list
				                           | Native.SHGFI.SHGFI_ATTRIBUTES // indicates that we want the item's attributes
				                           | Native.SHGFI.SHGFI_TYPENAME; // indicates that we want the item's type name
				Native.SHFILEINFO shInfo = new Native.SHFILEINFO();
				Native.Shell32.SHGetFileInfo((IntPtr) _pidl, 0, out shInfo, (uint) Marshal.SizeOf(shInfo), flags);

				// read item attributes
				Native.SFGAO attributeFlags = (Native.SFGAO) shInfo.dwAttributes;

				// create the item's IShellFolder interface
				if ((attributeFlags & Native.SFGAO.SFGAO_FOLDER) != 0)
				{
					Guid iidIShellFolder = new Guid(IID.IID_IShellFolder);
					if (_pidl == _rootItem._pidl)
					{
						// if the requested PIDL is the root namespace (the desktop) we can't use the the BindToObject method, so get it directly
						hResult = Native.Shell32.SHGetDesktopFolder(ref _shellFolder);
					}
					else
					{
						if (relativePidl)
							hResult = (int) parentShellItem._shellFolder.BindToObject(tempPidl, IntPtr.Zero, ref iidIShellFolder, out _shellFolder);
						else
							hResult = (int) _rootItem._shellFolder.BindToObject(tempPidl, IntPtr.Zero, ref iidIShellFolder, out _shellFolder);
					}

					if (hResult != 0)
					{
						// some objects are marked as folders, but really aren't and thus cannot be bound to an IShellFolder
						// log these events for future study, but it's not exactly something to be concerned about in isolated cases.
						// Marshal.ThrowExceptionForHR(hResult);
						if ((attributeFlags & Native.SFGAO.SFGAO_HASSUBFOLDER) == 0)
							attributeFlags = attributeFlags & ~Native.SFGAO.SFGAO_FOLDER;
					}
				}

				_displayName = shInfo.szDisplayName;
				_typeName = shInfo.szTypeName;
				_iconIndex = shInfo.iIcon;
				_isFolder = (attributeFlags & Native.SFGAO.SFGAO_FOLDER) != 0;
				_isVirtual = (attributeFlags & Native.SFGAO.SFGAO_FILESYSTEM) == 0;
				_hasSubFolders = (attributeFlags & Native.SFGAO.SFGAO_HASSUBFOLDER) != 0;
			}
			catch (Exception ex)
			{
				// if an exception happens during construction, we must release the PIDL now (remember, it's a pointer!)
				if (_pidl != null)
					_pidl.Dispose();
				throw new Exception("Creation of the specified shell item failed.", ex);
			}

#if DEBUG
			_instanceCount++;
#endif
		}
Example #23
0
        /// <summary>
        /// Runs/opens a program, document, directory (folder), URL, new email, Control Panel item etc.
        /// The returned <see cref="RResult"/> variable contains some process info - process id etc.
        /// </summary>
        /// <param name="file">
        /// Examples:
        /// - <c>@"C:\file.txt"</c>
        /// - <c>folders.Documents</c>
        /// - <c>folders.System + "notepad.exe"</c>
        /// - <c>@"%folders.System%\notepad.exe"</c>
        /// - <c>@"%TMP%\file.txt"</c>
        /// - <c>"notepad.exe"</c>
        /// - <c>@"..\folder\x.exe"</c>
        /// - <c>"http://a.b.c/d"</c>
        /// - <c>"file:///path"</c>
        /// - <c>"mailto:[email protected]"</c>
        /// - <c>":: ITEMIDLIST"</c>
        /// - <c>@"shell:::{CLSID}"</c>
        /// - <c>@"shell:AppsFolder\Microsoft.WindowsCalculator_8wekyb3d8bbwe!App"</c>.
        /// More info in Remarks.
        /// </param>
        /// <param name="args">
        /// Command line arguments.
        /// This function expands environment variables if starts with <c>"%"</c> or <c>"\"%"</c>.
        /// </param>
        /// <param name="flags"></param>
        /// <param name="dirEtc">
        /// Allows to specify more parameters: current directory, verb, etc.
        /// If string, it sets initial current directory for the new process. If "", gets it from <i>file</i>. More info: <see cref="ROptions.CurrentDirectory"/>.
        /// </param>
        /// <exception cref="ArgumentException">Used both <b>ROptions.Verb</b> and <b>RFlags.Admin</b> and this process isn't admin.</exception>
        /// <exception cref="AuException">Failed. For example, the file does not exist.</exception>
        /// <remarks>
        /// It works like when you double-click a file icon. It may start new process or not. For example it may just activate window if the program is already running.
        /// Uses API <msdn>ShellExecuteEx</msdn>.
        /// Similar to <see cref="Process.Start(string, string)"/>.
        ///
        /// The <i>file</i> parameter can be:
        /// - Full path of a file or directory. Examples: <c>@"C:\file.txt"</c>, <c>folders.Documents</c>, <c>folders.System + "notepad.exe"</c>, <c>@"%folders.System%\notepad.exe"</c>.
        /// - Filename of a file or directory, like <c>"notepad.exe"</c>. The function calls <see cref="filesystem.searchPath"/>.
        /// - Path relative to <see cref="folders.ThisApp"/>. Examples: <c>"x.exe"</c>, <c>@"subfolder\x.exe"</c>, <c>@".\subfolder\x.exe"</c>, <c>@"..\another folder\x.exe"</c>.
        /// - URL. Examples: <c>"https://www.example.com"</c>, <c>"file:///path"</c>.
        /// - Email, like <c>"mailto:[email protected]"</c>. Subject, body etc also can be specified, and Google knows how.
        /// - Shell object's ITEMIDLIST like <c>":: ITEMIDLIST"</c>. See <see cref="Pidl.ToHexString"/>, <see cref="folders.shell"/>. Can be used to open virtual folders and items like Control Panel.
        /// - Shell object's parsing name, like <c>@"shell:::{CLSID}"</c> or <c>@"::{CLSID}"</c>. See <see cref="Pidl.ToShellString"/>. Can be used to open virtual folders and items like Control Panel.
        /// - To run a Windows Store App, use <c>@"shell:AppsFolder\WinStoreAppId"</c> format. Examples: <c>@"shell:AppsFolder\Microsoft.WindowsCalculator_8wekyb3d8bbwe!App"</c>, <c>@"shell:AppsFolder\windows.immersivecontrolpanel_cw5n1h2txyewy!microsoft.windows.immersivecontrolpanel"</c>. To discover the string use hotkey Ctrl+Shift+Q or function <see cref="WndUtil.GetWindowsStoreAppId"/> or Google.
        ///
        /// Supports environment variables, like <c>@"%TMP%\file.txt"</c>. See <see cref="pathname.expand"/>.
        /// </remarks>
        /// <seealso cref="wnd.find"/>
        /// <seealso cref="wnd.findOrRun"/>
        /// <seealso cref="wnd.runAndFind"/>
        /// <example>
        /// Run Notepad and wait for an active Notepad window.
        /// <code><![CDATA[
        /// run.it("notepad.exe");
        /// 1.s();
        /// wnd w = wnd.wait(10, true, "*- Notepad", "Notepad");
        /// ]]></code>
        /// Run Notepad or activate a Notepad window.
        /// <code><![CDATA[
        /// wnd w = wnd.findOrRun("*- Notepad", run: () => run.it("notepad.exe"));
        /// ]]></code>
        /// Run File Explorer and wait for new folder window. Ignores matching windows that already existed.
        /// <code><![CDATA[
        /// var w = wnd.runAndFind(
        ///     () => run.it(@"explorer.exe"),
        ///     10, cn: "CabinetWClass");
        /// ]]></code>
        /// </example>
        public static RResult it(string file, string args = null, RFlags flags = 0, ROptions dirEtc = null)
        {
            Api.SHELLEXECUTEINFO x = default;
            x.cbSize = Api.SizeOf(x);
            x.fMask  = Api.SEE_MASK_NOZONECHECKS | Api.SEE_MASK_NOASYNC | Api.SEE_MASK_CONNECTNETDRV | Api.SEE_MASK_UNICODE;
            x.nShow  = Api.SW_SHOWNORMAL;

            bool curDirFromFile = false;
            var  more           = dirEtc;

            if (more != null)
            {
                x.lpVerb = more.Verb;
                if (x.lpVerb != null)
                {
                    x.fMask |= Api.SEE_MASK_INVOKEIDLIST;                                   //makes slower. But verbs are rarely used.
                }
                if (more.CurrentDirectory is string cd)
                {
                    if (cd.Length == 0)
                    {
                        curDirFromFile = true;
                    }
                    else
                    {
                        cd = pathname.expand(cd);
                    }
                    x.lpDirectory = cd;
                }

                if (!more.OwnerWindow.IsEmpty)
                {
                    x.hwnd = more.OwnerWindow.Hwnd.Window;
                }

                switch (more.WindowState)
                {
                case ProcessWindowStyle.Hidden: x.nShow = Api.SW_HIDE; break;

                case ProcessWindowStyle.Minimized: x.nShow = Api.SW_SHOWMINIMIZED; break;

                case ProcessWindowStyle.Maximized: x.nShow = Api.SW_SHOWMAXIMIZED; break;
                }

                x.fMask &= ~more.FlagsRemove;
                x.fMask |= more.FlagsAdd;
            }

            if (flags.Has(RFlags.Admin))
            {
                if (x.lpVerb == null || x.lpVerb.Eqi("runas"))
                {
                    x.lpVerb = "runas";
                }
                else if (!uacInfo.isAdmin)
                {
                    throw new ArgumentException("Cannot use Verb with flag Admin, unless this process is admin");
                }
            }

            file = _NormalizeFile(false, file, out bool isFullPath, out bool isShellPath);
            Pidl pidl = null;

            if (isShellPath)                  //":: ITEMIDLIST" or "::{CLSID}..." (we convert it too because the API does not support many)
            {
                pidl = Pidl.FromString(file); //does not throw
                if (pidl != null)
                {
                    x.lpIDList = pidl.UnsafePtr;
                    x.fMask   |= Api.SEE_MASK_INVOKEIDLIST;
                }
                else
                {
                    x.lpFile = file;
                }
            }
            else
            {
                x.lpFile = file;

                if (curDirFromFile && isFullPath)
                {
                    x.lpDirectory = pathname.getDirectory(file);
                }
            }
            x.lpDirectory ??= Directory.GetCurrentDirectory();
            if (!args.NE())
            {
                x.lpParameters = pathname.expand(args);
            }

            if (0 == (flags & RFlags.ShowErrorUI))
            {
                x.fMask |= Api.SEE_MASK_FLAG_NO_UI;
            }
            if (0 == (flags & RFlags.WaitForExit))
            {
                x.fMask |= Api.SEE_MASK_NO_CONSOLE;
            }
            if (0 != (flags & RFlags.MostUsed))
            {
                x.fMask |= Api.SEE_MASK_FLAG_LOG_USAGE;
            }
            x.fMask |= Api.SEE_MASK_NOCLOSEPROCESS;

            WndUtil.EnableActivate(-1);

            bool waitForExit = 0 != (flags & RFlags.WaitForExit);
            bool needHandle  = flags.Has(RFlags.NeedProcessHandle);

            bool ok = false; int pid = 0, errorCode = 0;
            bool asUser = !flags.HasAny(RFlags.Admin | RFlags.InheritAdmin) && uacInfo.isAdmin;             //info: new process does not inherit uiAccess

            if (asUser)
            {
                ok = Cpp.Cpp_ShellExec(x, out pid, out int injectError, out int execError);
                if (!ok)
                {
                    if (injectError != 0)
                    {
                        print.warning("Failed to run as non-admin.");
                        asUser = false;
                    }
                    else
                    {
                        errorCode = execError;
                    }
                }
            }
            if (!asUser)
            {
                ok = Api.ShellExecuteEx(ref x);
                if (!ok)
                {
                    errorCode = lastError.code;
                }
            }
            pidl?.Dispose();
            if (!ok)
            {
                throw new AuException(errorCode, $"*run '{file}'");
            }

            var         R  = new RResult();
            WaitHandle_ ph = null;

            if (needHandle || waitForExit)
            {
                if (pid != 0)
                {
                    x.hProcess = Handle_.OpenProcess(pid, Api.PROCESS_ALL_ACCESS);
                }
                if (!x.hProcess.Is0)
                {
                    ph = new WaitHandle_(x.hProcess, true);
                }
            }

            if (!waitForExit)
            {
                if (pid != 0)
                {
                    R.ProcessId = pid;
                }
                else if (!x.hProcess.Is0)
                {
                    R.ProcessId = process.processIdFromHandle(x.hProcess);
                }
            }

            try {
                Api.AllowSetForegroundWindow();

                if (x.lpVerb != null && Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
                {
                    Thread.CurrentThread.Join(50);                     //need min 5-10 for file Properties. And not Sleep.
                }
                if (ph != null)
                {
                    if (waitForExit)
                    {
                        ph.WaitOne();
                        if (Api.GetExitCodeProcess(x.hProcess, out var exitCode))
                        {
                            R.ProcessExitCode = exitCode;
                        }
                    }
                    if (needHandle)
                    {
                        R.ProcessHandle = ph;
                    }
                }
            }
            finally {
                if (R.ProcessHandle == null)
                {
                    if (ph != null)
                    {
                        ph.Dispose();
                    }
                    else
                    {
                        x.hProcess.Dispose();
                    }
                }
            }

            return(R);

            //tested: works well in MTA thread.
            //rejected: in QM2, run also has a 'window' parameter. However it just makes limited, unclear etc, and therefore rarely used. Instead use wnd.findOrRun or Find/Run/Wait like in the examples.
            //rejected: in QM2, run also has 'autodelay'. Better don't add such hidden things. Let the script decide what to do.
        }
Example #24
0
		void IFolderCoordinatee.BrowseTo(Pidl pidl)
		{
			if (this.CurrentPidlCore != pidl)
			{
				this.BrowseToCore(pidl);
				this.OnCurrentPidlChanged(EventArgs.Empty);
			}
		}