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; } }
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 }
public ThumbnailListItem(Pidl pidl) { if (pidl == null) { throw new System.ArgumentNullException("pidl"); } InitializeIQueueItemVariables(_methodCountInternal); _pidl = Pidl.Create(pidl); }
public ThumbnailListItem(string path) { if (path == null || path.Length == 0) { throw new System.ArgumentNullException("path"); } InitializeIQueueItemVariables(_methodCountInternal); _pidl = Pidl.Create(path); }
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)); }
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));
/// <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; } } }
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); }
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(); }
public void Dispose() { if (_pidl != null) { _pidl.Dispose(); _pidl = null; } }
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))); }
internal FolderViewItem(Pidl pidl) : base(pidl.Path, pidl.VirtualPath, pidl.DisplayName, pidl.IsFolder, pidl.IsLink) {}
protected override void BrowseToCore(Pidl pidl) { _folderListView.BrowseToPidl(pidl); }
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; } }
protected abstract void BrowseToCore(Pidl pidl);
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; } }
public ThumbnailListItem(Aurigma.GraphicsMill.WinControls.StandardFolder standardFolder) { InitializeIQueueItemVariables(_methodCountInternal); _pidl = Pidl.Create(standardFolder); }
protected override void BrowseToCore(Pidl pidl) { _folderTreeView.BrowseTo(pidl); }
public void BrowseToPidl(Pidl pidl) { _suppressBrowseEvents = true; try { this.Browse(new ShellItem(pidl, _rootShellItem, false)); } catch (Exception ex) { HandleBrowseException(ex); } finally { _suppressBrowseEvents = false; } }
public ShellItem(Pidl pidl, ShellItem parentShellItem) : this(pidl, parentShellItem, true) {}
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 }
/// <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. }
void IFolderCoordinatee.BrowseTo(Pidl pidl) { if (this.CurrentPidlCore != pidl) { this.BrowseToCore(pidl); this.OnCurrentPidlChanged(EventArgs.Empty); } }