internal ErrObject() { }
public string Description { get { throw null; } set { } }
public int Erl { get { throw null; } }
+ public int HelpContext { get { throw null; } set { } }
+ public string HelpFile { get { throw null; } set { } }
public int LastDllError { get { throw null; } }
public int Number { get { throw null; } set { } }
+ public string Source { get { throw null; } set { } }
public void Clear() { }
public System.Exception GetException() { throw null; }
public void Raise(int Number, object Source = null, object Description = null, object HelpFile = null, object HelpContext = null) { }
public sealed partial class Information
{
internal Information() { }
+ public static int Erl() { throw null; }
public static Microsoft.VisualBasic.ErrObject Err() { throw null; }
public static bool IsArray(object VarName) { throw null; }
public static bool IsDate(object Expression) { throw null; }
public sealed partial class Interaction
{
internal Interaction() { }
+ public static void AppActivate(int ProcessId) { }
+ public static void AppActivate(string Title) { }
public static void Beep() { }
public static object CallByName(object ObjectRef, string ProcName, Microsoft.VisualBasic.CallType UseCallType, params object[] Args) { throw null; }
public static object Choose(double Index, params object[] Choice) { throw null; }
+ public static string Command() { throw null; }
public static object CreateObject(string ProgId, string ServerName = "") { throw null; }
+ public static void DeleteSetting(string AppName, string Section = null, string Key = null) { }
+ public static string Environ(string Expression) { throw null; }
+ public static string Environ(int Expression) { throw null; }
+ public static string[,] GetAllSettings(string AppName, string Section) { throw null; }
+ public static object GetObject(string PathName = null, string Class = null) { throw null; }
+ public static string GetSetting(string AppName, string Section, string Key, string Default = "") { throw null; }
public static object IIf(bool Expression, object TruePart, object FalsePart) { throw null; }
+ public static string InputBox(string Prompt, string Title = "", string DefaultResponse = "", int XPos = -1, int YPos = -1) { throw null; }
+ public static MsgBoxResult MsgBox(object Prompt, MsgBoxStyle Buttons = MsgBoxStyle.ApplicationModal, object Title = null) { throw null; }
public static string Partition(long Number, long Start, long Stop, long Interval) { throw null; }
+ public static void SaveSetting(string AppName, string Section, string Key, string Setting) { }
+ public static int Shell(string PathName, AppWinStyle Style = AppWinStyle.MinimizedFocus, bool Wait = false, int Timeout = -1) { throw null; }
public static object Switch(params object[] VarExpr) { throw null; }
}
public enum MsgBoxResult
<WarningsNotAsErrors>42025</WarningsNotAsErrors>
<DefineConstants>$(DefineConstants),LATEBINDING=True</DefineConstants>
<DefineConstants Condition="'$(TargetsWindows)' == 'true'">$(DefineConstants),PLATFORM_WINDOWS=True</DefineConstants>
+ <DefineConstants Condition="'$(TargetGroup)' == 'uap'">$(DefineConstants),PLATFORM_UAP=True</DefineConstants>
<NoWarn Condition="'$(TargetsWindows)' != 'true'">$(NoWarn);CA1823</NoWarn> <!-- Avoid unused fields warnings in Unix build -->
<AssemblyName>Microsoft.VisualBasic.Core</AssemblyName>
<NoStdLib>true</NoStdLib>
<Configurations>netcoreapp-Debug;netcoreapp-Release;netcoreapp-Windows_NT-Debug;netcoreapp-Windows_NT-Release;uap-Windows_NT-Debug;uap-Windows_NT-Release</Configurations>
</PropertyGroup>
<ItemGroup Condition="'$(TargetsWindows)' == 'true'">
- <Compile Include="Microsoft\VisualBasic\FileIO\FileSystem.Windows.vb" />
<Compile Include="Microsoft\VisualBasic\Helpers\NativeMethods.vb" />
<Compile Include="Microsoft\VisualBasic\Helpers\NativeTypes.vb" />
<Compile Include="Microsoft\VisualBasic\Helpers\SafeNativeMethods.vb" />
<Compile Include="Microsoft\VisualBasic\Helpers\UnsafeNativeMethods.vb" />
</ItemGroup>
- <ItemGroup Condition="'$(TargetsWindows)' != 'true'">
- <Compile Include="Microsoft\VisualBasic\FileIO\FileSystem.Unix.vb" />
- </ItemGroup>
<ItemGroup>
<Compile Include="Microsoft\VisualBasic\Collection.vb" />
<Compile Include="Microsoft\VisualBasic\ComClassAttribute.vb" />
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.Win32.Primitives" />
+ <Reference Condition="'$(TargetGroup)' != 'uap'" Include="Microsoft.Win32.Registry" />
<Reference Include="System.Collections" />
+ <Reference Include="System.Collections.NonGeneric" />
<Reference Include="System.Collections.Specialized" />
<Reference Include="System.ComponentModel" />
<Reference Include="System.ComponentModel.Primitives" />
Private m_ClearOnCapture As Boolean
Private m_DescriptionIsSet As Boolean
+ Private m_curSource As String
+ Private m_SourceIsSet As Boolean
+ Private m_curHelpFile As String
+ Private m_curHelpContext As Integer
+ Private m_HelpFileIsSet As Boolean
+ Private m_HelpContextIsSet As Boolean
+
Friend Sub New()
Me.Clear() 'need to do this so the fields are set to Empty string, not Nothing
End Sub
End Set
End Property
+ Public Property Source() As String
+ Get
+ 'Return the current Source if we've already calculated it.
+ If m_SourceIsSet Then
+ Return m_curSource
+ End If
+
+ If Not m_curException Is Nothing Then
+ Me.Source = m_curException.Source
+ Return m_curSource
+ Else
+ 'The default case. NOTE: falling into the default does not "Set" the property.
+ 'We only get here if the Err object was previously cleared.
+ '
+ Return ""
+ End If
+ End Get
+
+ Set(ByVal Value As String)
+ m_curSource = Value
+ m_SourceIsSet = True
+ End Set
+ End Property
+
''' <summary>
''' Determines what the correct error description should be.
''' If we don't have an exception that we are responding to then
End Set
End Property
+ Public Property HelpFile() As String
+ Get
+ If m_HelpFileIsSet Then
+ Return m_curHelpFile
+ End If
+
+ If Not m_curException Is Nothing Then
+ ParseHelpLink(m_curException.HelpLink)
+ Return m_curHelpFile
+ Else
+ 'The default case. NOTE: falling into the default does not "Set" the property.
+ 'We only get here if the Err object was previously cleared.
+ '
+ Return ""
+ End If
+ End Get
+
+ Set(ByVal Value As String)
+ m_curHelpFile = Value
+
+ m_HelpFileIsSet = True
+ End Set
+ End Property
+
+ Private Function MakeHelpLink(ByVal HelpFile As String, ByVal HelpContext As Integer) As String
+ Return HelpFile & "#" & CStr(HelpContext)
+ End Function
+
+ Private Sub ParseHelpLink(ByVal HelpLink As String)
+
+ Diagnostics.Debug.Assert((Not m_HelpContextIsSet) OrElse (Not m_HelpFileIsSet), "Why is this getting called?")
+
+ If HelpLink Is Nothing OrElse HelpLink.Length = 0 Then
+
+ If Not m_HelpContextIsSet Then
+ Me.HelpContext = 0
+ End If
+ If Not m_HelpFileIsSet Then
+ Me.HelpFile = ""
+ End If
+
+ Else
+
+ Dim iContext As Integer = m_InvariantCompareInfo.IndexOf(HelpLink, "#", Globalization.CompareOptions.Ordinal)
+
+ If iContext <> -1 Then
+ If Not m_HelpContextIsSet Then
+ If iContext < HelpLink.Length Then
+ Me.HelpContext = CInt(HelpLink.Substring(iContext + 1))
+ Else
+ Me.HelpContext = 0
+ End If
+ End If
+ If Not m_HelpFileIsSet Then
+ Me.HelpFile = HelpLink.Substring(0, iContext)
+ End If
+ Else
+ If Not m_HelpContextIsSet Then
+ Me.HelpContext = 0
+ End If
+ If Not m_HelpFileIsSet Then
+ Me.HelpFile = HelpLink
+ End If
+ End If
+
+ End If
+
+ End Sub
+
+ Public Property HelpContext() As Integer
+ Get
+ If m_HelpContextIsSet Then
+ Return m_curHelpContext
+ End If
+
+ If Not m_curException Is Nothing Then
+ ParseHelpLink(m_curException.HelpLink)
+ Return m_curHelpContext
+
+ Else
+ 'The default case. NOTE: falling into the default does not "Set" the property.
+ 'We only get here if the Err object was previously cleared.
+ '
+ Return 0
+ End If
+
+ Return m_curHelpContext
+ End Get
+
+ Set(ByVal Value As Integer)
+ m_curHelpContext = Value
+ m_HelpContextIsSet = True
+ End Set
+ End Property
+
Public Function GetException() As Exception
Return m_curException
End Function
Public Sub Clear()
m_curException = Nothing
m_curNumber = 0
+ m_curSource = ""
+ m_curHelpFile = ""
+ m_curHelpContext = 0
+ m_SourceIsSet = False
+ m_HelpFileIsSet = False
+ m_HelpContextIsSet = False
m_curDescription = ""
m_curErl = 0
m_NumberIsSet = False
End If
Me.Number = Number
+ If Not Source Is Nothing Then
+ Me.Source = CStr(Source)
+ Else
+ ' .NET Framework uses VBHost.GetWindowTitle() if available
+ ' but the VBHost type is not accessible here.
+ Dim FullName As String
+ Dim CommaPos As Integer
+
+ FullName = System.Reflection.Assembly.GetCallingAssembly().FullName
+ CommaPos = InStr(FullName, ",")
+ If CommaPos < 1 Then
+ Me.Source = FullName
+ Else
+ Me.Source = Left(FullName, CommaPos - 1)
+ End If
+ End If
+
+ If Not HelpFile Is Nothing Then
+ Me.HelpFile = CStr(HelpFile)
+ End If
+
+ If Not HelpContext Is Nothing Then
+ Me.HelpContext = CInt(HelpContext)
+ End If
+
If Not Description Is Nothing Then
Me.Description = CStr(Description)
ElseIf Not m_DescriptionIsSet Then
Dim e As Exception
e = MapNumberToException(m_curNumber, m_curDescription)
+ e.Source = m_curSource
+ e.HelpLink = MakeHelpLink(m_curHelpFile, m_curHelpContext)
m_ClearOnCapture = False
Throw e
End Sub
+++ /dev/null
-' Licensed to the .NET Foundation under one or more agreements.
-' The .NET Foundation licenses this file to you under the MIT license.
-' See the LICENSE file in the project root for more information.
-Option Explicit On
-Option Strict On
-
-Imports System
-
-Namespace Microsoft.VisualBasic.FileIO
- Partial Public Class FileSystem
- Private Shared Sub ShellCopyOrMove(operation As CopyOrMove, directory As FileOrDirectory, sourceDirectoryFullPath As String, targetDirectoryFullPath As String, showUI As UIOptionInternal, onUserCancel As UICancelOption)
- Throw New PlatformNotSupportedException(SR.NoShellCopyOrMove)
- End Sub
-
- Private Shared Sub ShellDelete(directoryFullPath As String, showUI As UIOptionInternal, recycle As RecycleOption, onUserCancel As UICancelOption, directory As FileOrDirectory)
- Throw New PlatformNotSupportedException(SR.NoShellDelete)
- End Sub
-
- ''' <summary>
- ''' Stub to prevent compile error, this will not get called on non Windows OS's
- ''' </summary>
- ''' <param name="sourceFileFullPath"></param>
- ''' <param name="destinationFileFullPath"></param>
- Private Shared Sub WinNTCopyOrMove(sourceFileFullPath As String, destinationFileFullPath As String)
- Throw New PlatformNotSupportedException()
- End Sub
- End Class
-
-End Namespace
+++ /dev/null
-' Licensed to the .NET Foundation under one or more agreements.
-' The .NET Foundation licenses this file to you under the MIT license.
-' See the LICENSE file in the project root for more information.
-Option Strict On
-Option Explicit On
-
-Imports System
-Imports System.ComponentModel
-Imports System.Diagnostics
-Imports System.Security
-Imports System.Text
-
-Imports Microsoft.VisualBasic.CompilerServices
-Imports Microsoft.VisualBasic.CompilerServices.NativeMethods
-Imports Microsoft.VisualBasic.CompilerServices.NativeTypes
-
-'''' IMPORTANT: Changes made to public interface of FileSystem should be reflected in FileSystemProxy.vb.
-
-Namespace Microsoft.VisualBasic.FileIO
-
- Partial Public Class FileSystem
- ''' <summary>
- ''' Sets relevant flags on the SHFILEOPSTRUCT and calls SHFileOperation to copy move file / directory.
- ''' </summary>
- ''' <param name="Operation">Copy or move.</param>
- ''' <param name="TargetType">The target is a file or directory?</param>
- ''' <param name="FullSourcePath">Full path to source directory / file.</param>
- ''' <param name="FullTargetPath">Full path to target directory / file.</param>
- ''' <param name="ShowUI">Show all dialogs or just the error dialogs.</param>
- ''' <param name="OnUserCancel">Throw exception or ignore if user cancels the operation.</param>
- ''' <remarks>
- ''' Copy/MoveFile will call this directly. Copy/MoveDirectory will call ShellCopyOrMoveDirectory first
- ''' to change the path if needed.
- ''' </remarks>
- Private Shared Sub ShellCopyOrMove(ByVal Operation As CopyOrMove, ByVal TargetType As FileOrDirectory,
- ByVal FullSourcePath As String, ByVal FullTargetPath As String, ByVal ShowUI As UIOptionInternal, ByVal OnUserCancel As UICancelOption)
- Debug.Assert(System.Enum.IsDefined(GetType(CopyOrMove), Operation))
- Debug.Assert(System.Enum.IsDefined(GetType(FileOrDirectory), TargetType))
- Debug.Assert(FullSourcePath <> "" And IO.Path.IsPathRooted(FullSourcePath), "Invalid FullSourcePath")
- Debug.Assert(FullTargetPath <> "" And IO.Path.IsPathRooted(FullTargetPath), "Invalid FullTargetPath")
- Debug.Assert(ShowUI <> UIOptionInternal.NoUI, "Why call ShellDelete if ShowUI is NoUI???")
-
- ' Set operation type.
- Dim OperationType As SHFileOperationType
- If Operation = CopyOrMove.Copy Then
- OperationType = SHFileOperationType.FO_COPY
- Else
- OperationType = SHFileOperationType.FO_MOVE
- End If
-
- ' Set operation details.
- Dim OperationFlags As ShFileOperationFlags = GetOperationFlags(ShowUI)
-
- ' *** Special action for Directory only. ***
- Dim FinalSourcePath As String = FullSourcePath
- If TargetType = FileOrDirectory.Directory Then
- ' Shell behavior: If target does not exist, create target and copy / move source CONTENT into target.
- ' If target exists, copy / move source into target.
- ' To have our behavior:
- ' If target does not exist, create target parent (or shell will throw) and call ShellCopyOrMove.
- ' If target exists, attach "\*" to FullSourcePath and call ShellCopyOrMove.
- ' In case of Move, since moving the directory, just create the target parent.
- If IO.Directory.Exists(FullTargetPath) Then
- FinalSourcePath = IO.Path.Combine(FullSourcePath, "*")
- Else
- IO.Directory.CreateDirectory(GetParentPath(FullTargetPath))
- End If
- End If
-
- 'Call into ShellFileOperation.
- ShellFileOperation(OperationType, OperationFlags, FinalSourcePath, FullTargetPath, OnUserCancel, TargetType)
-
- ' *** Special action for Directory only. ***
- ' In case target does exist, and it's a move, we actually move content and leave the source directory.
- ' Clean up here.
- If Operation = CopyOrMove.Move And TargetType = FileOrDirectory.Directory Then
- If IO.Directory.Exists(FullSourcePath) Then
- If IO.Directory.GetDirectories(FullSourcePath).Length = 0 _
- AndAlso IO.Directory.GetFiles(FullSourcePath).Length = 0 Then
- IO.Directory.Delete(FullSourcePath, recursive:=False)
- End If
- End If
- End If
-
- End Sub
-
- ''' <summary>
- ''' Sets relevant flags on the SHFILEOPSTRUCT and calls into SHFileOperation to delete file / directory.
- ''' </summary>
- ''' <param name="FullPath">Full path to the file / directory.</param>
- ''' <param name="ShowUI">ShowDialogs to display progress and confirmation dialogs. Otherwise HideDialogs.</param>
- ''' <param name="recycle">SendToRecycleBin to delete to Recycle Bin. Otherwise DeletePermanently.</param>
- ''' <param name="OnUserCancel">Throw exception or not if the operation was canceled (by user or errors in the system).</param>
- ''' <remarks>
- ''' We don't need to consider Recursive flag here since we already verify that in DeleteDirectory.
- ''' </remarks>
- Private Shared Sub ShellDelete(ByVal FullPath As String,
- ByVal ShowUI As UIOptionInternal, ByVal recycle As RecycleOption, ByVal OnUserCancel As UICancelOption, ByVal FileOrDirectory As FileOrDirectory)
-
- Debug.Assert(FullPath <> "" And IO.Path.IsPathRooted(FullPath), "FullPath must be a full path")
- Debug.Assert(ShowUI <> UIOptionInternal.NoUI, "Why call ShellDelete if ShowUI is NoUI???")
-
- ' Set fFlags to control the operation details.
- Dim OperationFlags As ShFileOperationFlags = GetOperationFlags(ShowUI)
- If (recycle = RecycleOption.SendToRecycleBin) Then
- OperationFlags = OperationFlags Or ShFileOperationFlags.FOF_ALLOWUNDO
- End If
-
- ShellFileOperation(SHFileOperationType.FO_DELETE, OperationFlags, FullPath, Nothing, OnUserCancel, FileOrDirectory)
- End Sub
-
- ''' <summary>
- ''' Calls NativeMethods.SHFileOperation with the given SHFILEOPSTRUCT, notifies the shell of change,
- ''' and throw exceptions if needed.
- ''' </summary>
- ''' <param name="OperationType">Value from SHFileOperationType, specifying Copy / Move / Delete</param>
- ''' <param name="OperationFlags">Value from ShFileOperationFlags, specifying overwrite, recycle bin, etc...</param>
- ''' <param name="FullSource">The full path to the source.</param>
- ''' <param name="FullTarget">The full path to the target. Nothing if this is a Delete operation.</param>
- ''' <param name="OnUserCancel">Value from UICancelOption, specifying to throw or not when user cancels the operation.</param>
- '''<remarks></remarks>
- Private Shared Sub ShellFileOperation(ByVal OperationType As SHFileOperationType, ByVal OperationFlags As ShFileOperationFlags,
- ByVal FullSource As String, ByVal FullTarget As String, ByVal OnUserCancel As UICancelOption, ByVal FileOrDirectory As FileOrDirectory)
-
- Debug.Assert(System.Enum.IsDefined(GetType(SHFileOperationType), OperationType))
- Debug.Assert(OperationType <> SHFileOperationType.FO_RENAME, "Don't call Shell to rename")
- Debug.Assert(FullSource <> "" And IO.Path.IsPathRooted(FullSource), "Invalid FullSource path")
- Debug.Assert(OperationType = SHFileOperationType.FO_DELETE OrElse (FullTarget <> "" And IO.Path.IsPathRooted(FullTarget)), "Invalid FullTarget path")
-
-
- ' Get the SHFILEOPSTRUCT
- Dim OperationInfo As SHFILEOPSTRUCT = GetShellOperationInfo(OperationType, OperationFlags, FullSource, FullTarget)
-
- Dim Result As Integer
- Try
- Result = NativeMethods.SHFileOperation(OperationInfo)
- ' Notify the shell in case some changes happened.
- NativeMethods.SHChangeNotify(SHChangeEventTypes.SHCNE_DISKEVENTS,
- SHChangeEventParameterFlags.SHCNF_DWORD, IntPtr.Zero, IntPtr.Zero)
- Catch
- Throw
- Finally
- End Try
-
- ' If the operation was canceled, check OnUserCancel and throw OperationCanceledException if needed.
- ' Otherwise, check the result and throw the appropriate exception if there is an error code.
- If OperationInfo.fAnyOperationsAborted Then
- If OnUserCancel = UICancelOption.ThrowException Then
- Throw New OperationCanceledException()
- End If
- ElseIf Result <> 0 Then
- ThrowWinIOError(Result)
- End If
- End Sub
- ''' <summary>
- ''' Returns an SHFILEOPSTRUCT used by SHFileOperation based on the given parameters.
- ''' </summary>
- ''' <param name="OperationType">One of the SHFileOperationType value: copy, move or delete.</param>
- ''' <param name="OperationFlags">Combination SHFileOperationFlags values: details of the operation.</param>
- ''' <param name="SourcePath">The source file / directory path.</param>
- ''' <param name="TargetPath">The target file / directory path. Nothing in case of delete.</param>
- ''' <returns>A fully initialized SHFILEOPSTRUCT.</returns>
- Private Shared Function GetShellOperationInfo(
- ByVal OperationType As SHFileOperationType, ByVal OperationFlags As ShFileOperationFlags,
- ByVal SourcePath As String, Optional ByVal TargetPath As String = Nothing) As SHFILEOPSTRUCT
- Debug.Assert(SourcePath <> "" And IO.Path.IsPathRooted(SourcePath), "Invalid SourcePath")
-
- Return GetShellOperationInfo(OperationType, OperationFlags, New String() {SourcePath}, TargetPath)
- End Function
-
- ''' <summary>
- ''' Returns an SHFILEOPSTRUCT used by SHFileOperation based on the given parameters.
- ''' </summary>
- ''' <param name="OperationType">One of the SHFileOperationType value: copy, move or delete.</param>
- ''' <param name="OperationFlags">Combination SHFileOperationFlags values: details of the operation.</param>
- ''' <param name="SourcePaths">A string array containing the paths of source files. Must not be empty.</param>
- ''' <param name="TargetPath">The target file / directory path. Nothing in case of delete.</param>
- ''' <returns>A fully initialized SHFILEOPSTRUCT.</returns>
- Private Shared Function GetShellOperationInfo(
- ByVal OperationType As SHFileOperationType, ByVal OperationFlags As ShFileOperationFlags,
- ByVal SourcePaths() As String, Optional ByVal TargetPath As String = Nothing) As SHFILEOPSTRUCT
- Debug.Assert(System.Enum.IsDefined(GetType(SHFileOperationType), OperationType), "Invalid OperationType")
- Debug.Assert(TargetPath = "" Or IO.Path.IsPathRooted(TargetPath), "Invalid TargetPath")
- Debug.Assert(SourcePaths IsNot Nothing AndAlso SourcePaths.Length > 0, "Invalid SourcePaths")
-
- Dim OperationInfo As SHFILEOPSTRUCT
-
- ' Set wFunc - the operation.
- OperationInfo.wFunc = CType(OperationType, UInteger)
-
- ' Set fFlags - the operation details.
- OperationInfo.fFlags = CType(OperationFlags, UShort)
-
- ' Set pFrom and pTo - the paths.
- OperationInfo.pFrom = GetShellPath(SourcePaths)
- If TargetPath Is Nothing Then
- OperationInfo.pTo = Nothing
- Else
- OperationInfo.pTo = GetShellPath(TargetPath)
- End If
-
- ' Set other fields.
- OperationInfo.hNameMappings = IntPtr.Zero
- ' Try to set hwnd to the process's MainWindowHandle. If exception occurs, use IntPtr.Zero, which is desktop.
- Try
- OperationInfo.hwnd = Process.GetCurrentProcess.MainWindowHandle
- Catch ex As Exception
- If TypeOf (ex) Is SecurityException OrElse
- TypeOf (ex) Is InvalidOperationException OrElse
- TypeOf (ex) Is NotSupportedException Then
- ' GetCurrentProcess can throw SecurityException. MainWindowHandle can throw InvalidOperationException or NotSupportedException.
- OperationInfo.hwnd = IntPtr.Zero
- Else
- Throw
- End If
- End Try
- OperationInfo.lpszProgressTitle = String.Empty ' We don't set this since we don't have any FOF_SIMPLEPROGRESS.
-
- Return OperationInfo
- End Function
-
- ''' <summary>
- ''' Return the ShFileOperationFlags based on the ShowUI option.
- ''' </summary>
- ''' <param name="ShowUI">UIOptionInternal value.</param>
- Private Shared Function GetOperationFlags(ByVal ShowUI As UIOptionInternal) As ShFileOperationFlags
- Dim OperationFlags As ShFileOperationFlags = m_SHELL_OPERATION_FLAGS_BASE
- If (ShowUI = UIOptionInternal.OnlyErrorDialogs) Then
- OperationFlags = OperationFlags Or m_SHELL_OPERATION_FLAGS_HIDE_UI
- End If
- Return OperationFlags
- End Function
-
- ''' <summary>
- ''' Returns the special path format required for pFrom and pTo of SHFILEOPSTRUCT. See NativeMethod.
- ''' </summary>
- ''' <param name="FullPath">The full path to be converted.</param>
- ''' <returns>A string in the required format.</returns>
- Private Shared Function GetShellPath(ByVal FullPath As String) As String
- Debug.Assert(FullPath <> "" And IO.Path.IsPathRooted(FullPath), "Must be full path")
-
- Return GetShellPath(New String() {FullPath})
- End Function
-
- ''' <summary>
- ''' Returns the special path format required for pFrom and pTo of SHFILEOPSTRUCT. See NativeMethod.
- ''' </summary>
- ''' <param name="FullPaths">A string array containing the paths for the operation.</param>
- ''' <returns>A string in the required format.</returns>
- Private Shared Function GetShellPath(ByVal FullPaths() As String) As String
-#If DEBUG Then
- Debug.Assert(FullPaths IsNot Nothing, "FullPaths is NULL")
- Debug.Assert(FullPaths.Length > 0, "FullPaths() is empty array")
- For Each FullPath As String In FullPaths
- Debug.Assert(FullPath <> "" And IO.Path.IsPathRooted(FullPath), FullPath)
- Next
-#End If
- ' Each path will end with a Null character.
- Dim MultiString As New StringBuilder()
- For Each FullPath As String In FullPaths
- MultiString.Append(FullPath & ControlChars.NullChar)
- Next
- ' Don't need to append another Null character since String always end with Null character by default.
- Debug.Assert(MultiString.ToString.EndsWith(ControlChars.NullChar, StringComparison.Ordinal))
-
- Return MultiString.ToString()
- End Function
-
-
- ''' <summary>
- ''' Given an error code from winerror.h, throw the appropriate exception.
- ''' </summary>
- ''' <param name="errorCode">An error code from winerror.h.</param>
- ''' <remarks>
- ''' - This method is based on sources\ndp\clr\src\BCL\System\IO\_Error.cs::WinIOError, except the following.
- ''' - Exception message does not contain the path since at this point it is normalized.
- ''' - Instead of using PInvoke of GetMessage and MakeHRFromErrorCode, use managed code.
- ''' </remarks>
- Private Shared Sub ThrowWinIOError(ByVal errorCode As Integer)
- Select Case errorCode
- Case NativeTypes.ERROR_FILE_NOT_FOUND
- Throw New IO.FileNotFoundException()
- Case NativeTypes.ERROR_PATH_NOT_FOUND
- Throw New IO.DirectoryNotFoundException()
- Case NativeTypes.ERROR_ACCESS_DENIED
- Throw New UnauthorizedAccessException()
- Case NativeTypes.ERROR_FILENAME_EXCED_RANGE
- Throw New IO.PathTooLongException()
- Case NativeTypes.ERROR_INVALID_DRIVE
- Throw New IO.DriveNotFoundException()
- Case NativeTypes.ERROR_OPERATION_ABORTED, NativeTypes.ERROR_CANCELLED
- Throw New OperationCanceledException()
- Case Else
- ' Including these from _Error.cs::WinIOError.
- 'Case NativeTypes.ERROR_ALREADY_EXISTS
- 'Case NativeTypes.ERROR_INVALID_PARAMETER
- 'Case NativeTypes.ERROR_SHARING_VIOLATION
- 'Case NativeTypes.ERROR_FILE_EXISTS
- Throw New IO.IOException((New Win32Exception(errorCode)).Message,
- System.Runtime.InteropServices.Marshal.GetHRForLastWin32Error())
- End Select
- End Sub
-
- Private Shared Sub WinNTCopyOrMove(sourceFileFullPath As String, destinationFileFullPath As String)
- Try
- Dim succeed As Boolean = NativeMethods.MoveFileEx(
- sourceFileFullPath, destinationFileFullPath, m_MOVEFILEEX_FLAGS)
- ' GetLastWin32Error has to be close to PInvoke call. FxCop rule.
- If Not succeed Then
- ThrowWinIOError(System.Runtime.InteropServices.Marshal.GetLastWin32Error())
- End If
- Catch
- Throw
- End Try
- End Sub
-
- ' Base operation flags used in shell IO operation.
- ' - DON'T move connected files as a group.
- ' - DON'T confirm directory creation - our silent copy / move do not.
- Private Const m_SHELL_OPERATION_FLAGS_BASE As ShFileOperationFlags =
- ShFileOperationFlags.FOF_NO_CONNECTED_ELEMENTS Or
- ShFileOperationFlags.FOF_NOCONFIRMMKDIR
-
- ' Hide UI operation flags for Delete.
- ' - DON'T show progress bar.
- ' - DON'T confirm (answer yes to everything). NOTE: In exception cases (read-only file), shell still asks.
- Private Const m_SHELL_OPERATION_FLAGS_HIDE_UI As ShFileOperationFlags =
- ShFileOperationFlags.FOF_SILENT Or
- ShFileOperationFlags.FOF_NOCONFIRMATION
-
- ' When calling MoveFileEx, set the following flags:
- ' - Simulate CopyFile and DeleteFile if copied to a different volume.
- ' - Replace contents of existing target with the contents of source file.
- ' - Do not return until the file has actually been moved on the disk.
- Private Const m_MOVEFILEEX_FLAGS As Integer = CInt(
- MoveFileExFlags.MOVEFILE_COPY_ALLOWED Or
- MoveFileExFlags.MOVEFILE_REPLACE_EXISTING Or
- MoveFileExFlags.MOVEFILE_WRITE_THROUGH)
- End Class
-End Namespace
Imports System.Text
Imports Microsoft.VisualBasic.CompilerServices
+#If PLATFORM_WINDOWS Then
+Imports Microsoft.VisualBasic.CompilerServices.NativeMethods
+Imports Microsoft.VisualBasic.CompilerServices.NativeTypes
+#End If
Imports ExUtils = Microsoft.VisualBasic.CompilerServices.ExceptionUtils
Namespace Microsoft.VisualBasic.FileIO
''' This class represents the file system on a computer. It allows browsing the existing drives, special directories;
''' and also contains some commonly use methods for IO tasks.
''' </summary>
- Partial Public Class FileSystem
+ Public Class FileSystem
''' <summary>
''' Return the names of all available drives on the computer.
''' </summary>
' but have write permission / ACL thus cannot see but can delete / overwrite destination.
If Environment.OSVersion.Platform = PlatformID.Win32NT Then ' Platforms supporting MoveFileEx.
- WinNTCopyOrMove(sourceFileFullPath, destinationFileFullPath)
+#If PLATFORM_WINDOWS Then
+ Try
+ Dim succeed As Boolean = NativeMethods.MoveFileEx(
+ sourceFileFullPath, destinationFileFullPath, m_MOVEFILEEX_FLAGS)
+ ' GetLastWin32Error has to be close to PInvoke call. FxCop rule.
+ If Not succeed Then
+ ThrowWinIOError(System.Runtime.InteropServices.Marshal.GetLastWin32Error())
+ End If
+ Catch
+ Throw
+ End Try
+#End If
Else ' Non Windows
' IO.File.Delete will not throw if destinationFileFullPath does not exist
' (user may not have permission to discover this, but have permission to overwrite),
End Function
''' <summary>
+ ''' Sets relevant flags on the SHFILEOPSTRUCT and calls SHFileOperation to copy move file / directory.
+ ''' </summary>
+ ''' <param name="Operation">Copy or move.</param>
+ ''' <param name="TargetType">The target is a file or directory?</param>
+ ''' <param name="FullSourcePath">Full path to source directory / file.</param>
+ ''' <param name="FullTargetPath">Full path to target directory / file.</param>
+ ''' <param name="ShowUI">Show all dialogs or just the error dialogs.</param>
+ ''' <param name="OnUserCancel">Throw exception or ignore if user cancels the operation.</param>
+ ''' <remarks>
+ ''' Copy/MoveFile will call this directly. Copy/MoveDirectory will call ShellCopyOrMoveDirectory first
+ ''' to change the path if needed.
+ ''' </remarks>
+ Private Shared Sub ShellCopyOrMove(ByVal Operation As CopyOrMove, ByVal TargetType As FileOrDirectory,
+ ByVal FullSourcePath As String, ByVal FullTargetPath As String, ByVal ShowUI As UIOptionInternal, ByVal OnUserCancel As UICancelOption)
+ Debug.Assert(System.Enum.IsDefined(GetType(CopyOrMove), Operation))
+ Debug.Assert(System.Enum.IsDefined(GetType(FileOrDirectory), TargetType))
+ Debug.Assert(FullSourcePath <> "" And IO.Path.IsPathRooted(FullSourcePath), "Invalid FullSourcePath")
+ Debug.Assert(FullTargetPath <> "" And IO.Path.IsPathRooted(FullTargetPath), "Invalid FullTargetPath")
+ Debug.Assert(ShowUI <> UIOptionInternal.NoUI, "Why call ShellDelete if ShowUI is NoUI???")
+
+#If PLATFORM_WINDOWS Then
+ ' Set operation type.
+ Dim OperationType As SHFileOperationType
+ If Operation = CopyOrMove.Copy Then
+ OperationType = SHFileOperationType.FO_COPY
+ Else
+ OperationType = SHFileOperationType.FO_MOVE
+ End If
+
+ ' Set operation details.
+ Dim OperationFlags As ShFileOperationFlags = GetOperationFlags(ShowUI)
+
+ ' *** Special action for Directory only. ***
+ Dim FinalSourcePath As String = FullSourcePath
+ If TargetType = FileOrDirectory.Directory Then
+ ' Shell behavior: If target does not exist, create target and copy / move source CONTENT into target.
+ ' If target exists, copy / move source into target.
+ ' To have our behavior:
+ ' If target does not exist, create target parent (or shell will throw) and call ShellCopyOrMove.
+ ' If target exists, attach "\*" to FullSourcePath and call ShellCopyOrMove.
+ ' In case of Move, since moving the directory, just create the target parent.
+ If IO.Directory.Exists(FullTargetPath) Then
+ FinalSourcePath = IO.Path.Combine(FullSourcePath, "*")
+ Else
+ IO.Directory.CreateDirectory(GetParentPath(FullTargetPath))
+ End If
+ End If
+
+ ' Call into ShellFileOperation.
+ ShellFileOperation(OperationType, OperationFlags, FinalSourcePath, FullTargetPath, OnUserCancel, TargetType)
+
+ ' *** Special action for Directory only. ***
+ ' In case target does exist, and it's a move, we actually move content and leave the source directory.
+ ' Clean up here.
+ If Operation = CopyOrMove.Move And TargetType = FileOrDirectory.Directory Then
+ If IO.Directory.Exists(FullSourcePath) Then
+ If IO.Directory.GetDirectories(FullSourcePath).Length = 0 _
+ AndAlso IO.Directory.GetFiles(FullSourcePath).Length = 0 Then
+ IO.Directory.Delete(FullSourcePath, recursive:=False)
+ End If
+ End If
+ End If
+#Else
+ Throw New PlatformNotSupportedException(SR.NoShellCopyOrMove)
+#End If
+
+ End Sub
+
+ ''' <summary>
+ ''' Sets relevant flags on the SHFILEOPSTRUCT and calls into SHFileOperation to delete file / directory.
+ ''' </summary>
+ ''' <param name="FullPath">Full path to the file / directory.</param>
+ ''' <param name="ShowUI">ShowDialogs to display progress and confirmation dialogs. Otherwise HideDialogs.</param>
+ ''' <param name="recycle">SendToRecycleBin to delete to Recycle Bin. Otherwise DeletePermanently.</param>
+ ''' <param name="OnUserCancel">Throw exception or not if the operation was canceled (by user or errors in the system).</param>
+ ''' <remarks>
+ ''' We don't need to consider Recursive flag here since we already verify that in DeleteDirectory.
+ ''' </remarks>
+ Private Shared Sub ShellDelete(ByVal FullPath As String,
+ ByVal ShowUI As UIOptionInternal, ByVal recycle As RecycleOption, ByVal OnUserCancel As UICancelOption, ByVal FileOrDirectory As FileOrDirectory)
+
+ Debug.Assert(FullPath <> "" And IO.Path.IsPathRooted(FullPath), "FullPath must be a full path")
+ Debug.Assert(ShowUI <> UIOptionInternal.NoUI, "Why call ShellDelete if ShowUI is NoUI???")
+
+#If PLATFORM_WINDOWS Then
+ ' Set fFlags to control the operation details.
+ Dim OperationFlags As ShFileOperationFlags = GetOperationFlags(ShowUI)
+ If (recycle = RecycleOption.SendToRecycleBin) Then
+ OperationFlags = OperationFlags Or ShFileOperationFlags.FOF_ALLOWUNDO
+ End If
+
+ ShellFileOperation(SHFileOperationType.FO_DELETE, OperationFlags, FullPath, Nothing, OnUserCancel, FileOrDirectory)
+#Else
+ Throw New PlatformNotSupportedException(SR.NoShellCopyOrMove)
+#End If
+ End Sub
+
+#If PLATFORM_WINDOWS Then
+ ''' <summary>
+ ''' Calls NativeMethods.SHFileOperation with the given SHFILEOPSTRUCT, notifies the shell of change,
+ ''' and throw exceptions if needed.
+ ''' </summary>
+ ''' <param name="OperationType">Value from SHFileOperationType, specifying Copy / Move / Delete</param>
+ ''' <param name="OperationFlags">Value from ShFileOperationFlags, specifying overwrite, recycle bin, etc...</param>
+ ''' <param name="FullSource">The full path to the source.</param>
+ ''' <param name="FullTarget">The full path to the target. Nothing if this is a Delete operation.</param>
+ ''' <param name="OnUserCancel">Value from UICancelOption, specifying to throw or not when user cancels the operation.</param>
+ Private Shared Sub ShellFileOperation(ByVal OperationType As SHFileOperationType, ByVal OperationFlags As ShFileOperationFlags,
+ ByVal FullSource As String, ByVal FullTarget As String, ByVal OnUserCancel As UICancelOption, ByVal FileOrDirectory As FileOrDirectory)
+
+ Debug.Assert(System.Enum.IsDefined(GetType(SHFileOperationType), OperationType))
+ Debug.Assert(OperationType <> SHFileOperationType.FO_RENAME, "Don't call Shell to rename")
+ Debug.Assert(FullSource <> "" And IO.Path.IsPathRooted(FullSource), "Invalid FullSource path")
+ Debug.Assert(OperationType = SHFileOperationType.FO_DELETE OrElse (FullTarget <> "" And IO.Path.IsPathRooted(FullTarget)), "Invalid FullTarget path")
+
+ ' Get the SHFILEOPSTRUCT
+ Dim OperationInfo As SHFILEOPSTRUCT = GetShellOperationInfo(OperationType, OperationFlags, FullSource, FullTarget)
+
+ Dim Result As Integer
+ Try
+ Result = NativeMethods.SHFileOperation(OperationInfo)
+ ' Notify the shell in case some changes happened.
+ NativeMethods.SHChangeNotify(SHChangeEventTypes.SHCNE_DISKEVENTS,
+ SHChangeEventParameterFlags.SHCNF_DWORD, IntPtr.Zero, IntPtr.Zero)
+ Catch
+ Throw
+ Finally
+ End Try
+
+ ' If the operation was canceled, check OnUserCancel and throw OperationCanceledException if needed.
+ ' Otherwise, check the result and throw the appropriate exception if there is an error code.
+ If OperationInfo.fAnyOperationsAborted Then
+ If OnUserCancel = UICancelOption.ThrowException Then
+ Throw New OperationCanceledException()
+ End If
+ ElseIf Result <> 0 Then
+ ThrowWinIOError(Result)
+ End If
+ End Sub
+
+ ''' <summary>
+ ''' Returns an SHFILEOPSTRUCT used by SHFileOperation based on the given parameters.
+ ''' </summary>
+ ''' <param name="OperationType">One of the SHFileOperationType value: copy, move or delete.</param>
+ ''' <param name="OperationFlags">Combination SHFileOperationFlags values: details of the operation.</param>
+ ''' <param name="SourcePath">The source file / directory path.</param>
+ ''' <param name="TargetPath">The target file / directory path. Nothing in case of delete.</param>
+ ''' <returns>A fully initialized SHFILEOPSTRUCT.</returns>
+ Private Shared Function GetShellOperationInfo(
+ ByVal OperationType As SHFileOperationType, ByVal OperationFlags As ShFileOperationFlags,
+ ByVal SourcePath As String, Optional ByVal TargetPath As String = Nothing) As SHFILEOPSTRUCT
+ Debug.Assert(SourcePath <> "" And IO.Path.IsPathRooted(SourcePath), "Invalid SourcePath")
+
+ Return GetShellOperationInfo(OperationType, OperationFlags, New String() {SourcePath}, TargetPath)
+ End Function
+
+ ''' <summary>
+ ''' Returns an SHFILEOPSTRUCT used by SHFileOperation based on the given parameters.
+ ''' </summary>
+ ''' <param name="OperationType">One of the SHFileOperationType value: copy, move or delete.</param>
+ ''' <param name="OperationFlags">Combination SHFileOperationFlags values: details of the operation.</param>
+ ''' <param name="SourcePaths">A string array containing the paths of source files. Must not be empty.</param>
+ ''' <param name="TargetPath">The target file / directory path. Nothing in case of delete.</param>
+ ''' <returns>A fully initialized SHFILEOPSTRUCT.</returns>
+ Private Shared Function GetShellOperationInfo(
+ ByVal OperationType As SHFileOperationType, ByVal OperationFlags As ShFileOperationFlags,
+ ByVal SourcePaths() As String, Optional ByVal TargetPath As String = Nothing) As SHFILEOPSTRUCT
+ Debug.Assert(System.Enum.IsDefined(GetType(SHFileOperationType), OperationType), "Invalid OperationType")
+ Debug.Assert(TargetPath = "" Or IO.Path.IsPathRooted(TargetPath), "Invalid TargetPath")
+ Debug.Assert(SourcePaths IsNot Nothing AndAlso SourcePaths.Length > 0, "Invalid SourcePaths")
+
+ Dim OperationInfo As SHFILEOPSTRUCT
+
+ ' Set wFunc - the operation.
+ OperationInfo.wFunc = CType(OperationType, UInteger)
+
+ ' Set fFlags - the operation details.
+ OperationInfo.fFlags = CType(OperationFlags, UShort)
+
+ ' Set pFrom and pTo - the paths.
+ OperationInfo.pFrom = GetShellPath(SourcePaths)
+ If TargetPath Is Nothing Then
+ OperationInfo.pTo = Nothing
+ Else
+ OperationInfo.pTo = GetShellPath(TargetPath)
+ End If
+
+ ' Set other fields.
+ OperationInfo.hNameMappings = IntPtr.Zero
+ ' Try to set hwnd to the process's MainWindowHandle. If exception occurs, use IntPtr.Zero, which is desktop.
+ Try
+ OperationInfo.hwnd = Process.GetCurrentProcess.MainWindowHandle
+ Catch ex As Exception
+ If TypeOf (ex) Is SecurityException OrElse
+ TypeOf (ex) Is InvalidOperationException OrElse
+ TypeOf (ex) Is NotSupportedException Then
+ ' GetCurrentProcess can throw SecurityException. MainWindowHandle can throw InvalidOperationException or NotSupportedException.
+ OperationInfo.hwnd = IntPtr.Zero
+ Else
+ Throw
+ End If
+ End Try
+ OperationInfo.lpszProgressTitle = String.Empty ' We don't set this since we don't have any FOF_SIMPLEPROGRESS.
+
+ Return OperationInfo
+ End Function
+
+ ''' <summary>
+ ''' Return the ShFileOperationFlags based on the ShowUI option.
+ ''' </summary>
+ ''' <param name="ShowUI">UIOptionInternal value.</param>
+ Private Shared Function GetOperationFlags(ByVal ShowUI As UIOptionInternal) As ShFileOperationFlags
+ Dim OperationFlags As ShFileOperationFlags = m_SHELL_OPERATION_FLAGS_BASE
+ If (ShowUI = UIOptionInternal.OnlyErrorDialogs) Then
+ OperationFlags = OperationFlags Or m_SHELL_OPERATION_FLAGS_HIDE_UI
+ End If
+ Return OperationFlags
+ End Function
+
+ ''' <summary>
+ ''' Returns the special path format required for pFrom and pTo of SHFILEOPSTRUCT. See NativeMethod.
+ ''' </summary>
+ ''' <param name="FullPath">The full path to be converted.</param>
+ ''' <returns>A string in the required format.</returns>
+ Private Shared Function GetShellPath(ByVal FullPath As String) As String
+ Debug.Assert(FullPath <> "" And IO.Path.IsPathRooted(FullPath), "Must be full path")
+
+ Return GetShellPath(New String() {FullPath})
+ End Function
+
+ ''' <summary>
+ ''' Returns the special path format required for pFrom and pTo of SHFILEOPSTRUCT. See NativeMethod.
+ ''' </summary>
+ ''' <param name="FullPaths">A string array containing the paths for the operation.</param>
+ ''' <returns>A string in the required format.</returns>
+ Private Shared Function GetShellPath(ByVal FullPaths() As String) As String
+#If DEBUG Then
+ Debug.Assert(FullPaths IsNot Nothing, "FullPaths is NULL")
+ Debug.Assert(FullPaths.Length > 0, "FullPaths() is empty array")
+ For Each FullPath As String In FullPaths
+ Debug.Assert(FullPath <> "" And IO.Path.IsPathRooted(FullPath), FullPath)
+ Next
+#End If
+
+ ' Each path will end with a Null character.
+ Dim MultiString As New StringBuilder()
+ For Each FullPath As String In FullPaths
+ MultiString.Append(FullPath & ControlChars.NullChar)
+ Next
+ ' Don't need to append another Null character since String always end with Null character by default.
+ Debug.Assert(MultiString.ToString.EndsWith(ControlChars.NullChar, StringComparison.Ordinal))
+
+ Return MultiString.ToString()
+ End Function
+#End If
+
+ ''' <summary>
''' Throw an argument exception if the given path starts with "\\.\" (device path).
''' </summary>
''' <param name="path">The path to check.</param>
End If
End Sub
+#If PLATFORM_WINDOWS Then
+ ''' <summary>
+ ''' Given an error code from winerror.h, throw the appropriate exception.
+ ''' </summary>
+ ''' <param name="errorCode">An error code from winerror.h.</param>
+ ''' <remarks>
+ ''' - This method is based on sources\ndp\clr\src\BCL\System\IO\_Error.cs::WinIOError, except the following.
+ ''' - Exception message does not contain the path since at this point it is normalized.
+ ''' - Instead of using PInvoke of GetMessage and MakeHRFromErrorCode, use managed code.
+ ''' </remarks>
+ Private Shared Sub ThrowWinIOError(ByVal errorCode As Integer)
+ Select Case errorCode
+ Case NativeTypes.ERROR_FILE_NOT_FOUND
+ Throw New IO.FileNotFoundException()
+ Case NativeTypes.ERROR_PATH_NOT_FOUND
+ Throw New IO.DirectoryNotFoundException()
+ Case NativeTypes.ERROR_ACCESS_DENIED
+ Throw New UnauthorizedAccessException()
+ Case NativeTypes.ERROR_FILENAME_EXCED_RANGE
+ Throw New IO.PathTooLongException()
+ Case NativeTypes.ERROR_INVALID_DRIVE
+ Throw New IO.DriveNotFoundException()
+ Case NativeTypes.ERROR_OPERATION_ABORTED, NativeTypes.ERROR_CANCELLED
+ Throw New OperationCanceledException()
+ Case Else
+ ' Including these from _Error.cs::WinIOError.
+ 'Case NativeTypes.ERROR_ALREADY_EXISTS
+ 'Case NativeTypes.ERROR_INVALID_PARAMETER
+ 'Case NativeTypes.ERROR_SHARING_VIOLATION
+ 'Case NativeTypes.ERROR_FILE_EXISTS
+ Throw New IO.IOException((New Win32Exception(errorCode)).Message,
+ System.Runtime.InteropServices.Marshal.GetHRForLastWin32Error())
+ End Select
+ End Sub
+#End If
+
''' <summary>
''' Convert UIOption to UIOptionInternal to use internally.
''' </summary>
Throw New InvalidEnumArgumentException(argName, argValue, GetType(UICancelOption))
End Sub
+#If PLATFORM_WINDOWS Then
+ ' Base operation flags used in shell IO operation.
+ ' - DON'T move connected files as a group.
+ ' - DON'T confirm directory creation - our silent copy / move do not.
+ Private Const m_SHELL_OPERATION_FLAGS_BASE As ShFileOperationFlags =
+ ShFileOperationFlags.FOF_NO_CONNECTED_ELEMENTS Or
+ ShFileOperationFlags.FOF_NOCONFIRMMKDIR
+
+ ' Hide UI operation flags for Delete.
+ ' - DON'T show progress bar.
+ ' - DON'T confirm (answer yes to everything). NOTE: In exception cases (read-only file), shell still asks.
+ Private Const m_SHELL_OPERATION_FLAGS_HIDE_UI As ShFileOperationFlags =
+ ShFileOperationFlags.FOF_SILENT Or
+ ShFileOperationFlags.FOF_NOCONFIRMATION
+
+ ' When calling MoveFileEx, set the following flags:
+ ' - Simulate CopyFile and DeleteFile if copied to a different volume.
+ ' - Replace contents of existing target with the contents of source file.
+ ' - Do not return until the file has actually been moved on the disk.
+ Private Const m_MOVEFILEEX_FLAGS As Integer = CInt(
+ MoveFileExFlags.MOVEFILE_COPY_ALLOWED Or
+ MoveFileExFlags.MOVEFILE_REPLACE_EXISTING Or
+ MoveFileExFlags.MOVEFILE_WRITE_THROUGH)
+#End If
+
' Array containing all the path separator chars. Used to verify that input is a name, not a path.
Private Shared ReadOnly m_SeparatorChars() As Char = {
IO.Path.DirectorySeparatorChar, IO.Path.AltDirectorySeparatorChar, IO.Path.VolumeSeparatorChar}
Imports System
Imports System.Environment
-Imports System.Security
+Imports System.Reflection
Imports Microsoft.VisualBasic.CompilerServices.Utils
Imports ExUtils = Microsoft.VisualBasic.CompilerServices.ExceptionUtils
''' </remarks>
Public Shared ReadOnly Property CurrentUserApplicationData() As String
Get
- Throw New PlatformNotSupportedException()
+ Return GetDirectoryPath(GetWindowsFormsDirectory("System.Windows.Forms.Application", "UserAppDataPath"), SR.IO_SpecialDirectory_UserAppData)
End Get
End Property
''' </remarks>
Public Shared ReadOnly Property AllUsersApplicationData() As String
Get
- Throw New PlatformNotSupportedException()
+ Return GetDirectoryPath(GetWindowsFormsDirectory("System.Windows.Forms.Application", "CommonAppDataPath"), SR.IO_SpecialDirectory_AllUserAppData)
End Get
End Property
Return FileSystem.NormalizePath(Directory)
End Function
+ Private Shared Function GetWindowsFormsDirectory(typeName As String, propertyName As String) As String
+ Dim type As Type = type.GetType($"{typeName}, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError:=False)
+ Dim [property] As PropertyInfo = type?.GetProperty(propertyName)
+ If [property] Is Nothing Then
+ Return ""
+ End If
+ Return DirectCast([property].GetValue(Nothing, BindingFlags.DoNotWrapExceptions, Nothing, Nothing, Nothing), String)
+ End Function
+
End Class
End Namespace
End Enum
''' <summary>
- ''' Contains information about the current state of both physical and virtual memory, including extended memory.
- ''' </summary>
- <StructLayout(LayoutKind.Sequential)>
- Friend Structure MEMORYSTATUSEX
- 'typedef struct _MEMORYSTATUSEX {
- ' DWORD dwLength; Size of the structure. Must set before calling GlobalMemoryStatusEx.
- ' DWORD dwMemoryLoad; Number between 0 and 100 on current memory utilization.
- ' DWORDLONG ullTotalPhys; Total size of physical memory.
- ' DWORDLONG ullAvailPhys; Total size of available physical memory.
- ' DWORDLONG ullTotalPageFile; Size of committed memory limit.
- ' DWORDLONG ullAvailPageFile; Size of available memory to committed (ullTotalPageFile max).
- ' DWORDLONG ullTotalVirtual; Total size of user potion of virtual address space of calling process.
- ' DWORDLONG ullAvailVirtual; Total size of unreserved and uncommitted memory in virtual address space.
- ' DWORDLONG ullAvailExtendedVirtual; Total size of unreserved and uncommitted memory in extended portion of virual address.
- '} MEMORYSTATUSEX, *LPMEMORYSTATUSEX;
-
- Friend dwLength As UInt32
- Friend dwMemoryLoad As UInt32
- Friend ullTotalPhys As UInt64
- Friend ullAvailPhys As UInt64
- Friend ullTotalPageFile As UInt64
- Friend ullAvailPageFile As UInt64
- Friend ullTotalVirtual As UInt64
- Friend ullAvailVirtual As UInt64
- Friend ullAvailExtendedVirtual As UInt64
-
- Friend Sub Init()
- dwLength = CType(Marshal.SizeOf(GetType(MEMORYSTATUSEX)), UInt32)
- End Sub
- End Structure
-
- ''' <summary>
- ''' Obtains information about the system's current usage of both physical and virtual memory.
- ''' </summary>
- ''' <param name="lpBuffer">Pointer to a MEMORYSTATUSEX structure.</param>
- ''' <returns>True if the function succeeds. Otherwise, False.</returns>
- <DllImport("Kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
- Friend Shared Function GlobalMemoryStatusEx(ByRef lpBuffer As MEMORYSTATUSEX) As <MarshalAsAttribute(UnmanagedType.Bool)> Boolean
- End Function
-
- ''' <summary>
''' The MoveFileEx function moves an existing file or directory.
''' http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/movefileex.asp
''' </summary>
<ComponentModel.EditorBrowsableAttribute(ComponentModel.EditorBrowsableState.Never)>
Friend NotInheritable Class NativeTypes
- <StructLayout(LayoutKind.Sequential)>
- Friend NotInheritable Class SECURITY_ATTRIBUTES
- Implements IDisposable
-
- Friend Sub New()
- nLength = System.Runtime.InteropServices.Marshal.SizeOf(GetType(SECURITY_ATTRIBUTES))
- End Sub
-
- Public nLength As Integer
- Public lpSecurityDescriptor As IntPtr
- Public bInheritHandle As Boolean
-
- Public Overloads Sub Dispose() Implements IDisposable.Dispose
- If lpSecurityDescriptor <> IntPtr.Zero Then
- UnsafeNativeMethods.LocalFree(lpSecurityDescriptor)
- lpSecurityDescriptor = IntPtr.Zero
- End If
- GC.SuppressFinalize(Me)
- End Sub
-
- Protected Overrides Sub Finalize()
- Dispose()
- MyBase.Finalize()
- End Sub
- End Class
-
- ''' <summary>
- ''' Represent Win32 PROCESS_INFORMATION structure. IMPORTANT: Copy the handles to a SafeHandle before use them.
- ''' </summary>
- ''' <remarks>
- ''' The handles in PROCESS_INFORMATION are initialized in unmanaged function.
- ''' We can't use SafeHandle here because Interop doesn't support [out] SafeHandles in structure / classes yet.
- ''' This class makes no attempt to free the handles. To use the handle, first copy it to a SafeHandle class
- ''' (using LateInitSafeHandleZeroOrMinusOneIsInvalid.InitialSetHandle) to correctly use and dispose the handle.
- ''' </remarks>
- <StructLayout(LayoutKind.Sequential)>
- Friend NotInheritable Class PROCESS_INFORMATION
- Public hProcess As IntPtr = IntPtr.Zero
- Public hThread As IntPtr = IntPtr.Zero
- Public dwProcessId As Integer
- Public dwThreadId As Integer
-
- Friend Sub New()
- End Sub
- End Class
-
- ''' <summary>
- ''' Important! This class should be used where the API being called has allocated the strings. That is why lpReserved, etc. are declared as IntPtrs instead
- ''' of Strings - so that the marshaling layer won't release the memory. This caused us problems in the shell() functions. We would call GetStartupInfo()
- ''' which doesn't expect the memory for the strings to be freed. But because the strings were previously defined as type String, the marshaller would
- ''' and we got memory corruption problems detectable while running AppVerifier.
- ''' If you use this structure with an API like CreateProcess() then you are supplying the strings so you'll need another version of this class that defines lpReserved, etc.
- ''' as String so that the memory will get cleaned up.
- ''' </summary>
- ''' <remarks></remarks>
- <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)>
- Friend NotInheritable Class STARTUPINFO
- Implements IDisposable
-
- Public cb As Integer
- Public lpReserved As IntPtr = IntPtr.Zero 'not string - see summary
- Public lpDesktop As IntPtr = IntPtr.Zero 'not string - see summary
- Public lpTitle As IntPtr = IntPtr.Zero 'not string - see summary
- Public dwX As Integer
- Public dwY As Integer
- Public dwXSize As Integer
- Public dwYSize As Integer
- Public dwXCountChars As Integer
- Public dwYCountChars As Integer
- Public dwFillAttribute As Integer
- Public dwFlags As Integer
- Public wShowWindow As Short
- Public cbReserved2 As Short
- Public lpReserved2 As IntPtr = IntPtr.Zero
- Public hStdInput As IntPtr = IntPtr.Zero
- Public hStdOutput As IntPtr = IntPtr.Zero
- Public hStdError As IntPtr = IntPtr.Zero
-
- Friend Sub New()
- End Sub
-
- Private m_HasBeenDisposed As Boolean ' To detect redundant calls. Default initialize = False.
-
- Protected Overrides Sub Finalize()
- Dispose(False)
- End Sub
-
- ' IDisposable
- Private Sub Dispose(ByVal disposing As Boolean)
- If Not m_HasBeenDisposed Then
- If disposing Then
- m_HasBeenDisposed = True
-
- Const STARTF_USESTDHANDLES As Integer = 256 'Defined in windows.h
- If (Me.dwFlags And STARTF_USESTDHANDLES) <> 0 Then
- If hStdInput <> IntPtr.Zero AndAlso hStdInput <> NativeTypes.INVALID_HANDLE Then
- NativeMethods.CloseHandle(hStdInput)
- hStdInput = NativeTypes.INVALID_HANDLE
- End If
-
- If hStdOutput <> IntPtr.Zero AndAlso hStdOutput <> NativeTypes.INVALID_HANDLE Then
- NativeMethods.CloseHandle(hStdOutput)
- hStdOutput = NativeTypes.INVALID_HANDLE
- End If
-
- If hStdError <> IntPtr.Zero AndAlso hStdError <> NativeTypes.INVALID_HANDLE Then
- NativeMethods.CloseHandle(hStdError)
- hStdError = NativeTypes.INVALID_HANDLE
- End If
- End If 'Me.dwFlags and STARTF_USESTDHANDLES
-
- End If
- End If
- End Sub
-
- ' This code correctly implements the disposable pattern.
- Friend Sub Dispose() Implements IDisposable.Dispose
- ' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.
- Dispose(True)
- GC.SuppressFinalize(Me)
- End Sub
- End Class
-
<StructLayout(LayoutKind.Sequential)> Friend NotInheritable Class SystemTime
Public wYear As Short
Public wMonth As Short
MOVEFILE_WRITE_THROUGH = &H8
End Enum
- ' Handle Values
- Friend Shared ReadOnly INVALID_HANDLE As IntPtr = New IntPtr(-1)
-
- ' GetWindow() Constants
- Friend Const GW_HWNDFIRST As Integer = 0
- Friend Const GW_HWNDLAST As Integer = 1
- Friend Const GW_HWNDNEXT As Integer = 2
- Friend Const GW_HWNDPREV As Integer = 3
- Friend Const GW_OWNER As Integer = 4
- Friend Const GW_CHILD As Integer = 5
- Friend Const GW_MAX As Integer = 5
-
- 'Friend Const EVENTLOG_INFORMATION_TYPE As Integer = 0
-
- Friend Const STARTF_USESHOWWINDOW As Integer = 1
-
- Friend Const NORMAL_PRIORITY_CLASS As Integer = &H20
-
Friend Const LCMAP_TRADITIONAL_CHINESE As Integer = &H4000000I
Friend Const LCMAP_SIMPLIFIED_CHINESE As Integer = &H2000000I
Friend Const LCMAP_UPPERCASE As Integer = &H200I
End Function
+ Public Function Erl() As Integer
+ Dim oProj As ProjectData
+ oProj = ProjectData.GetProjectData()
+ Erl = oProj.m_Err.Erl
+ End Function
+
Public Function IsArray(ByVal VarName As Object) As Boolean
If VarName Is Nothing Then
' See the LICENSE file in the project root for more information.
Imports System
+Imports System.Reflection
Imports System.Text
Imports System.Runtime.InteropServices
+#If Not PLATFORM_UAP Then
+Imports Microsoft.Win32
+#End If
+
Imports Microsoft.VisualBasic.CompilerServices
Imports Microsoft.VisualBasic.CompilerServices.ExceptionUtils
Imports Microsoft.VisualBasic.CompilerServices.Utils
Namespace Microsoft.VisualBasic
Public Module Interaction
+ Private m_SortedEnvList As System.Collections.SortedList
+
+ '============================================================================
+ ' Application/system interaction functions.
+ '============================================================================
+
+ Public Function Shell(ByVal PathName As String, Optional ByVal Style As AppWinStyle = AppWinStyle.MinimizedFocus, Optional ByVal Wait As Boolean = False, Optional ByVal Timeout As Integer = -1) As Integer
+ Return DirectCast(InvokeMethod("Shell", PathName, Style, Wait, Timeout), Integer)
+ End Function
+
+ Public Sub AppActivate(ByVal ProcessId As Integer)
+ InvokeMethod("AppActivateByProcessId", ProcessId)
+ End Sub
+
+ Public Sub AppActivate(ByVal Title As String)
+ InvokeMethod("AppActivateByTitle", Title)
+ End Sub
+
+ Private m_CommandLine As String
+
+ Public Function Command() As String
+
+ If m_CommandLine Is Nothing Then
+ Dim s As String = Environment.CommandLine
+
+ 'The first element of the array is the .exe name
+ ' we must remove this when building the return value
+ If (s Is Nothing) OrElse (s.Length = 0) Then
+ Return ""
+ End If
+
+ 'The following code must remove the application name from the command line
+ ' without disturbing the arguments (trailing and embedded spaces)
+ '
+ 'We also need to handle embedded spaces in the application name
+ ' as well as skipping over quotations used around embedded spaces within
+ ' the application name
+ ' examples:
+ ' f:\"Program Files"\Microsoft\foo.exe a b d e f
+ ' "f:\"Program Files"\Microsoft\foo.exe" a b d e f
+ ' f:\Program Files\Microsoft\foo.exe a b d e f
+ Dim LengthOfAppName, j As Integer
+
+ 'Remove the app name from the arguments
+ LengthOfAppName = Environment.GetCommandLineArgs(0).Length
+
+ Do
+ j = s.IndexOf(ChrW(34), j)
+ If j >= 0 AndAlso j <= LengthOfAppName Then
+ s = s.Remove(j, 1)
+ End If
+ Loop While (j >= 0 AndAlso j <= LengthOfAppName)
+
+ If j = 0 OrElse j > s.Length Then
+ m_CommandLine = ""
+ Else
+ m_CommandLine = LTrim(s.Substring(LengthOfAppName))
+ End If
+ End If
+ Return m_CommandLine
+ End Function
+
+ Public Function Environ(ByVal Expression As Integer) As String
+
+ 'Validate index - Note that unlike the fx, this is a legacy VB function and the index is 1 based.
+ If Expression <= 0 OrElse Expression > 255 Then
+ Throw New ArgumentException(GetResourceString(SR.Argument_Range1toFF1, "Expression"))
+ End If
+
+ If m_SortedEnvList Is Nothing Then
+ SyncLock m_EnvironSyncObject
+ If m_SortedEnvList Is Nothing Then
+ 'Constructing the sorted environment list is extremely slow, so we keep a copy around. This list must be alphabetized to match vb5/vb6 behavior
+ m_SortedEnvList = New System.Collections.SortedList(Environment.GetEnvironmentVariables())
+ End If
+ End SyncLock
+ End If
+
+ If Expression > m_SortedEnvList.Count Then
+ Return ""
+ End If
+
+ Dim EnvVarName As String = m_SortedEnvList.GetKey(Expression - 1).ToString()
+ Dim EnvVarValue As String = m_SortedEnvList.GetByIndex(Expression - 1).ToString()
+ Return (EnvVarName & "=" & EnvVarValue)
+ End Function
+
+ Private m_EnvironSyncObject As New Object
+
+ Public Function Environ(ByVal Expression As String) As String
+ Expression = Trim(Expression)
+
+ If Expression.Length = 0 Then
+ Throw New ArgumentException(GetResourceString(SR.Argument_InvalidValue1, "Expression"))
+ End If
+
+ Return Environment.GetEnvironmentVariable(Expression)
+ End Function
'============================================================================
' User interaction functions.
#End If
End Sub
+ Public Function InputBox(ByVal Prompt As String, Optional ByVal Title As String = "", Optional ByVal DefaultResponse As String = "", Optional ByVal XPos As Integer = -1, Optional ByVal YPos As Integer = -1) As String
+ Return DirectCast(InvokeMethod("InputBox", Prompt, Title, DefaultResponse, XPos, YPos), String)
+ End Function
+
+ Public Function MsgBox(ByVal Prompt As Object, Optional ByVal Buttons As MsgBoxStyle = MsgBoxStyle.OkOnly, Optional ByVal Title As Object = Nothing) As MsgBoxResult
+ Return DirectCast(InvokeMethod("MsgBox", Prompt, Buttons, Title), MsgBoxResult)
+ End Function
+
+ Private Function InvokeMethod(methodName As String, ParamArray args As Object()) As Object
+ Dim type As Type = type.GetType("Microsoft.VisualBasic._Interaction, Microsoft.VisualBasic.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError:=False)
+ Dim method As MethodInfo = type?.GetMethod(methodName)
+ If method Is Nothing Then
+ Throw New PlatformNotSupportedException(SR.MethodRequiresSystemWindowsForms)
+ End If
+ Return method.Invoke(Nothing, BindingFlags.DoNotWrapExceptions, Nothing, args, Nothing)
+ End Function
+
'============================================================================
' String functions.
'============================================================================
Return Nothing 'If nothing matched above
End Function
+ '============================================================================
+ ' Registry functions.
+ '============================================================================
+
+ Public Sub DeleteSetting(ByVal AppName As String, Optional ByVal Section As String = Nothing, Optional ByVal Key As String = Nothing)
+#If PLATFORM_UAP Then
+ Throw New PlatformNotSupportedException()
+#Else
+ Dim AppSection As String
+ Dim UserKey As RegistryKey
+ Dim AppSectionKey As RegistryKey = Nothing
+
+ CheckPathComponent(AppName)
+ AppSection = FormRegKey(AppName, Section)
+
+ Try
+ UserKey = Registry.CurrentUser
+
+ If IsNothing(Key) OrElse (Key.Length = 0) Then
+ UserKey.DeleteSubKeyTree(AppSection)
+ Else
+ AppSectionKey = UserKey.OpenSubKey(AppSection, True)
+ If AppSectionKey Is Nothing Then
+ Throw New ArgumentException(GetResourceString(SR.Argument_InvalidValue1, "Section"))
+ End If
+
+ AppSectionKey.DeleteValue(Key)
+ End If
+
+ Catch ex As Exception
+ Throw ex
+ Finally
+ If AppSectionKey IsNot Nothing Then
+ AppSectionKey.Close()
+ End If
+ End Try
+#End If
+ End Sub
+
+ Public Function GetAllSettings(ByVal AppName As String, ByVal Section As String) As String(,)
+#If PLATFORM_UAP Then
+ Throw New PlatformNotSupportedException()
+#Else
+ Dim rk As RegistryKey
+ Dim sAppSect As String
+ Dim i As Integer
+ Dim lUpperBound As Integer
+ Dim sValueNames() As String
+ Dim sValues(,) As String
+ Dim o As Object
+ Dim sName As String
+
+ ' Check for empty string in path
+ CheckPathComponent(AppName)
+ CheckPathComponent(Section)
+ sAppSect = FormRegKey(AppName, Section)
+ rk = Registry.CurrentUser.OpenSubKey(sAppSect)
+
+
+ If rk Is Nothing Then
+ Return Nothing
+ End If
+
+ GetAllSettings = Nothing
+ Try
+ If rk.ValueCount <> 0 Then
+ sValueNames = rk.GetValueNames()
+ lUpperBound = sValueNames.GetUpperBound(0)
+ ReDim sValues(lUpperBound, 1)
+
+ For i = 0 To lUpperBound
+ sName = sValueNames(i)
+
+ 'Assign name
+ sValues(i, 0) = sName
+
+ 'Assign value
+ o = rk.GetValue(sName)
+
+ If (Not o Is Nothing) AndAlso (TypeOf o Is String) Then
+ sValues(i, 1) = o.ToString()
+ End If
+ Next i
+
+ GetAllSettings = sValues
+ End If
+
+ Catch ex As StackOverflowException
+ Throw ex
+ Catch ex As OutOfMemoryException
+ Throw ex
+ Catch ex As System.Threading.ThreadAbortException
+ Throw ex
+
+ Catch ex As Exception
+ 'Consume the exception
+
+ Finally
+ rk.Close()
+ End Try
+#End If
+ End Function
+
+ Public Function GetSetting(ByVal AppName As String, ByVal Section As String, ByVal Key As String, Optional ByVal [Default] As String = "") As String
+#If PLATFORM_UAP Then
+ Throw New PlatformNotSupportedException()
+#Else
+ Dim rk As RegistryKey = Nothing
+ Dim sAppSect As String
+ Dim o As Object
+
+ 'Check for empty strings
+ CheckPathComponent(AppName)
+ CheckPathComponent(Section)
+ CheckPathComponent(Key)
+ If [Default] Is Nothing Then
+ [Default] = ""
+ End If
+
+ 'Open the sub key
+ sAppSect = FormRegKey(AppName, Section)
+ Try
+ rk = Registry.CurrentUser.OpenSubKey(sAppSect) 'By default, does not request write permission
+
+ 'Get the key's value
+ If rk Is Nothing Then
+ Return [Default]
+ End If
+
+ o = rk.GetValue(Key, [Default])
+ Finally
+ If rk IsNot Nothing Then
+ rk.Close()
+ End If
+ End Try
+
+ If o Is Nothing Then
+ Return Nothing
+ ElseIf TypeOf o Is String Then ' - odd that this is required to be a string when it isn't in GetAllSettings() above...
+ Return DirectCast(o, String)
+ Else
+ Throw New ArgumentException(GetResourceString(SR.Argument_InvalidValue))
+ End If
+#End If
+ End Function
+
+ Public Sub SaveSetting(ByVal AppName As String, ByVal Section As String, ByVal Key As String, ByVal Setting As String)
+#If PLATFORM_UAP Then
+ Throw New PlatformNotSupportedException()
+#Else
+ Dim rk As RegistryKey
+ Dim sIniSect As String
+
+ ' Check for empty string in path
+ CheckPathComponent(AppName)
+ CheckPathComponent(Section)
+ CheckPathComponent(Key)
+
+ sIniSect = FormRegKey(AppName, Section)
+ rk = Registry.CurrentUser.CreateSubKey(sIniSect)
+
+ If rk Is Nothing Then
+ 'Subkey could not be created
+ Throw New ArgumentException(GetResourceString(SR.Interaction_ResKeyNotCreated1, sIniSect))
+ End If
+
+ Try
+ rk.SetValue(Key, Setting)
+ Catch ex As Exception
+ Throw ex
+ Finally
+ rk.Close()
+ End Try
+#End If
+ End Sub
+
+ '============================================================================
+ ' Private functions.
+ '============================================================================
+ Private Function FormRegKey(ByVal sApp As String, ByVal sSect As String) As String
+ Const REGISTRY_INI_ROOT As String = "Software\VB and VBA Program Settings"
+ 'Forms the string for the key value
+ If IsNothing(sApp) OrElse (sApp.Length = 0) Then
+ FormRegKey = REGISTRY_INI_ROOT
+ ElseIf IsNothing(sSect) OrElse (sSect.Length = 0) Then
+ FormRegKey = REGISTRY_INI_ROOT & "\" & sApp
+ Else
+ FormRegKey = REGISTRY_INI_ROOT & "\" & sApp & "\" & sSect
+ End If
+ End Function
+
+ Private Sub CheckPathComponent(ByVal s As String)
+ If (s Is Nothing) OrElse (s.Length = 0) Then
+ Throw New ArgumentException(GetResourceString(SR.Argument_PathNullOrEmpty))
+ End If
+ End Sub
+
Public Function CreateObject(ByVal ProgId As String, Optional ByVal ServerName As String = "") As Object
'Creates local or remote COM2 objects. Should not be used to create COM+ objects.
'Applications that need to be STA should set STA either on their Sub Main via STAThreadAttribute
End Try
End Function
+ Public Function GetObject(Optional ByVal PathName As String = Nothing, Optional ByVal [Class] As String = Nothing) As Object
+ 'Only works for Com2 objects, not for COM+ objects.
+
+ If Len([Class]) = 0 Then
+ Try
+ Return Marshal.BindToMoniker([PathName])
+ Catch ex As StackOverflowException
+ Throw ex
+ Catch ex As OutOfMemoryException
+ Throw ex
+ Catch ex As System.Threading.ThreadAbortException
+ Throw ex
+ Catch
+ Throw VbMakeException(vbErrors.CantCreateObject)
+ End Try
+ Else
+ If PathName Is Nothing Then
+ Return Nothing
+ ElseIf Len(PathName) = 0 Then
+ Try
+ Dim t As Type = Type.GetTypeFromProgID([Class])
+ Return System.Activator.CreateInstance(t)
+ Catch ex As StackOverflowException
+ Throw ex
+ Catch ex As OutOfMemoryException
+ Throw ex
+ Catch ex As System.Threading.ThreadAbortException
+ Throw ex
+ Catch
+ Throw VbMakeException(vbErrors.CantCreateObject)
+ End Try
+ Else
+ Return Nothing
+ End If
+ End If
+ End Function
+
'============================================================================
' Object/latebound functions.
'============================================================================
<data name="NoShellDelete" xml:space="preserve">
<value>UI not available for delete</value>
</data>
-</root>
\ No newline at end of file
+ <data name="MethodRequiresSystemWindowsForms" xml:space="preserve">
+ <value>Method requires System.Windows.Forms.</value>
+ </data>
+</root>
[Fact]
public void Clear()
{
+ ProjectData.ClearProjectError();
ProjectData.SetProjectError(new ArgumentException(), 3);
var errObj = Information.Err();
errObj.Number = 5;
errObj.Description = "Description";
+ errObj.HelpContext = 6;
+ errObj.HelpFile = "File";
+ errObj.Source = "Source";
errObj.Clear();
Assert.Equal(0, errObj.Erl);
+ Assert.Equal(0, errObj.HelpContext);
+ Assert.Equal("", errObj.HelpFile);
+ Assert.Equal("", errObj.Source);
Assert.Equal(0, errObj.LastDllError);
Assert.Equal(0, errObj.Number);
Assert.Equal("", errObj.Description);
Assert.Null(errObj.GetException());
+ Assert.Equal(0, Information.Erl());
}
[Fact]
public void Raise()
{
+ ProjectData.ClearProjectError();
+
ProjectData.SetProjectError(new Exception());
_ = Assert.Throws<ArgumentException>(() => Information.Err().Raise(0)).ToString();
}
[Fact]
+ public void Source()
+ {
+ ProjectData.ClearProjectError();
+
+ ProjectData.SetProjectError(new Exception() { Source = null });
+ Assert.Null(Information.Err().Source);
+
+ ProjectData.SetProjectError(new Exception() { Source = "MySource1" });
+ Assert.Equal("MySource1", Information.Err().Source);
+
+ ProjectData.SetProjectError(new Exception() { Source = null });
+ Assert.Null(Information.Err().Source);
+
+ ProjectData.SetProjectError(new Exception() { Source = null });
+ _ = Assert.Throws<OutOfMemoryException>(() => Information.Err().Raise(7, Source: "MySource2"));
+ Assert.Equal("MySource2", Information.Err().Source);
+ }
+
+ [Fact]
public void FilterDefaultMessage()
{
+ ProjectData.ClearProjectError();
+
string message = "Description";
ProjectData.SetProjectError(new System.IO.FileNotFoundException(message));
Assert.Equal(message, Information.Err().Description);
ProjectData.SetProjectError(new System.IO.FileNotFoundException(message));
Assert.NotEqual(message, Information.Err().Description);
}
+
+ [Fact]
+ public void MakeHelpLink()
+ {
+ ProjectData.ClearProjectError();
+
+ ProjectData.SetProjectError(new ArgumentException());
+ Assert.Equal("#0", Assert.Throws<OutOfMemoryException>(() => Information.Err().Raise(7)).HelpLink);
+
+ ProjectData.SetProjectError(new ArgumentException());
+ Assert.Equal("#3", Assert.Throws<OutOfMemoryException>(() => Information.Err().Raise(7, HelpContext: 3)).HelpLink);
+
+ ProjectData.SetProjectError(new ArgumentException());
+ Assert.Equal("MyFile1#3", Assert.Throws<OutOfMemoryException>(() => Information.Err().Raise(7, HelpFile: "MyFile1")).HelpLink);
+
+ ProjectData.ClearProjectError();
+ ProjectData.SetProjectError(new ArgumentException());
+ Assert.Equal("MyFile2#0", Assert.Throws<OutOfMemoryException>(() => Information.Err().Raise(7, HelpFile: "MyFile2")).HelpLink);
+
+ ProjectData.SetProjectError(new ArgumentException());
+ Assert.Equal("MyFile3#3", Assert.Throws<OutOfMemoryException>(() => Information.Err().Raise(7, HelpContext: 3, HelpFile: "MyFile3")).HelpLink);
+ }
+
+ [Theory]
+ [InlineData(null, 0, "")]
+ [InlineData("", 0, "")]
+ [InlineData("#0", 0, "")]
+ [InlineData("#1", 1, "")]
+ [InlineData("#-3", -3, "")]
+ [InlineData("MyFile1", 0, "MyFile1")]
+ [InlineData("MyFile4#4", 4, "MyFile4")]
+ public void ParseHelpLink(string helpLink, int expectedHelpContext, string expectedHelpFile)
+ {
+ ProjectData.ClearProjectError();
+ ProjectData.SetProjectError(new ArgumentException() { HelpLink = helpLink });
+ Assert.Equal(expectedHelpContext, Information.Err().HelpContext);
+ Assert.Equal(expectedHelpFile, Information.Err().HelpFile);
+ }
+
+ [Theory]
+ [InlineData("#")]
+ [InlineData("##")]
+ [InlineData("##2")]
+ [InlineData("MyFile2#")]
+ [InlineData("MyFile3##")]
+ public void ParseHelpLink_InvalidCastException(string helpLink)
+ {
+ ProjectData.ClearProjectError();
+ ProjectData.SetProjectError(new ArgumentException() { HelpLink = helpLink });
+ Assert.Throws<InvalidCastException>(() => Information.Err().HelpContext);
+ Assert.Throws<InvalidCastException>(() => Information.Err().HelpFile);
+ }
}
}
using System;
using System.Collections.Generic;
+using System.Linq;
using Xunit;
namespace Microsoft.VisualBasic.Tests
{
public class InteractionTests
{
+ private static readonly bool s_SupportRegistry = !PlatformDetection.IsUap;
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNetCore))]
+ public void AppActivate_ProcessId()
+ {
+ InvokeMissingMethod(() => Interaction.AppActivate(42));
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNetCore))]
+ public void AppActivate_Title()
+ {
+ InvokeMissingMethod(() => Interaction.AppActivate("MyProcess"));
+ }
+
[Theory]
[MemberData(nameof(CallByName_TestData))]
public void CallByName(object instance, string methodName, CallType useCallType, object[] args, Func<object, object> getResult, object expected)
}
}
-
[Fact]
public void Choose()
{
}
[Fact]
+ public void Command()
+ {
+ var expected = Environment.CommandLine;
+ var actual = Interaction.Command();
+ Assert.False(string.IsNullOrEmpty(actual));
+ Assert.EndsWith(actual, expected);
+ }
+
+ [Fact]
public void CreateObject()
{
Assert.Throws<NullReferenceException>(() => Interaction.CreateObject(null));
yield return new object[] { false, 3, "str", "str" };
yield return new object[] { true, 3, "str", 3 };
}
+
+ [Fact]
+ public void DeleteSetting()
+ {
+ if (s_SupportRegistry)
+ {
+ Assert.Throws<ArgumentException>(() => Interaction.DeleteSetting(AppName: "", Section: null, Key: null));
+ }
+ else
+ {
+ Assert.Throws<PlatformNotSupportedException>(() => Interaction.DeleteSetting(AppName: "", Section: null, Key: null));
+ }
+ // Not tested: valid arguments.
+ }
+
+ [Fact]
+ public void Environ_Index()
+ {
+ var pairs = GetEnvironmentVariables();
+ int n = Math.Min(pairs.Length, 255);
+
+ // Exception.ToString() called to verify message is constructed successfully.
+ _ = Assert.Throws<ArgumentException>(() => Interaction.Environ(0)).ToString();
+ _ = Assert.Throws<ArgumentException>(() => Interaction.Environ(256)).ToString();
+
+ for (int i = 0; i < n; i++)
+ {
+ var pair = pairs[i];
+ Assert.Equal($"{pair.Item1}={pair.Item2}", Interaction.Environ(i + 1));
+ }
+
+ for (int i = n; i < 255; i++)
+ {
+ Assert.Equal("", Interaction.Environ(i + 1));
+ }
+ }
+
+ [Fact]
+ public void Environ_Name()
+ {
+ var pairs = GetEnvironmentVariables();
+
+ // Exception.ToString() called to verify message is constructed successfully.
+ _ = Assert.Throws<ArgumentException>(() => Interaction.Environ("")).ToString();
+ _ = Assert.Throws<ArgumentException>(() => Interaction.Environ(" ")).ToString();
+
+ foreach (var (key, value) in pairs)
+ {
+ Assert.Equal(value, Interaction.Environ(key));
+ }
+
+ if (pairs.Length > 0)
+ {
+ var (key, value) = pairs[pairs.Length - 1];
+ Assert.Equal(value, Interaction.Environ(" " + key));
+ Assert.Equal(value, Interaction.Environ(key + " "));
+ Assert.Null(Interaction.Environ(key + "z"));
+ }
+ }
+
+ private static (string, string)[] GetEnvironmentVariables()
+ {
+ var pairs = new List<(string, string)>();
+ var vars = Environment.GetEnvironmentVariables();
+ foreach (var key in vars.Keys) {
+ pairs.Add(((string)key, (string)vars[key]));
+ }
+ return pairs.OrderBy(pair => pair.Item1).ToArray();
+ }
+
+ [Fact]
+ public void GetAllSettings()
+ {
+ if (s_SupportRegistry)
+ {
+ Assert.Throws<ArgumentException>(() => Interaction.GetAllSettings(AppName: "", Section: ""));
+ }
+ else
+ {
+ Assert.Throws<PlatformNotSupportedException>(() => Interaction.GetAllSettings(AppName: "", Section: ""));
+ }
+ // Not tested: valid arguments.
+ }
+
+ [Fact]
+ public void GetSetting()
+ {
+ if (s_SupportRegistry)
+ {
+ Assert.Throws<ArgumentException>(() => Interaction.GetSetting(AppName: "", Section: "", Key: "", Default: ""));
+ }
+ else
+ {
+ Assert.Throws<PlatformNotSupportedException>(() => Interaction.GetSetting(AppName: "", Section: "", Key: "", Default: ""));
+ }
+ // Not tested: valid arguments.
+ }
+
+ [Fact]
+ public void GetObject()
+ {
+ Assert.Throws<Exception>(() => Interaction.GetObject());
+ Assert.Throws<Exception>(() => Interaction.GetObject("", null));
+ Assert.Throws<Exception>(() => Interaction.GetObject(null, ""));
+ Assert.Throws<Exception>(() => Interaction.GetObject("", ""));
+ // Not tested: valid arguments.
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNetCore))]
+ public void InputBox()
+ {
+ InvokeMissingMethod(() => Interaction.InputBox("Prompt", Title: "", DefaultResponse: "", XPos: -1, YPos: -1));
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNetCore))]
+ public void MsgBox()
+ {
+ InvokeMissingMethod(() => Interaction.MsgBox("Prompt", Buttons: MsgBoxStyle.ApplicationModal, Title: null));
+ }
[Theory]
[InlineData(0, 1, 2, 1, " :0")]
{
Assert.Throws<OverflowException>(() => Interaction.Partition(Number, Start, Stop, Interval));
}
+
+ [Fact]
+ public void SaveSetting()
+ {
+ if (s_SupportRegistry)
+ {
+ Assert.Throws<ArgumentException>(() => Interaction.SaveSetting(AppName: "", Section: "", Key: "", Setting: ""));
+
+ }
+ else
+ {
+ Assert.Throws<PlatformNotSupportedException>(() => Interaction.SaveSetting(AppName: "", Section: "", Key: "", Setting: ""));
+ }
+ // Not tested: valid arguments.
+ }
+
+ [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNetCore))]
+ public void Shell()
+ {
+ InvokeMissingMethod(() => Interaction.Shell("MyPath", Style: AppWinStyle.NormalFocus, Wait: false, Timeout: -1));
+ }
[Theory]
[InlineData(null, null)] // empty
{
Assert.Throws<ArgumentException>(() => Interaction.Switch(true, "a", false));
}
+
+ // Methods that rely on reflection of missing assembly.
+ private static void InvokeMissingMethod(Action action)
+ {
+ // Exception.ToString() called to verify message is constructed successfully.
+ _ = Assert.Throws<PlatformNotSupportedException>(action).ToString();
+ }
}
}
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Supported on netfx")]
public static void AllUsersApplicationDataFolderTest()
{
- Assert.Throws<PlatformNotSupportedException>(() => SpecialDirectories.AllUsersApplicationData);
+ Assert.Throws<System.IO.DirectoryNotFoundException>(() => SpecialDirectories.AllUsersApplicationData);
}
[Fact]
[SkipOnTargetFramework(TargetFrameworkMonikers.NetFramework, "Supported on netfx")]
public static void CurrentUserApplicationDataFolderTest()
{
- Assert.Throws<PlatformNotSupportedException>(() => SpecialDirectories.CurrentUserApplicationData);
+ Assert.Throws<System.IO.DirectoryNotFoundException>(() => SpecialDirectories.CurrentUserApplicationData);
}
[Fact]