How to tell if Folder is opened in explorer - vb.net

I'm writing a script in Siemens NX using vb.net, which helps export drawing files. The file will be exported into a folder, that is kind of bothersome to manually navigate to, so I want to open said folder up to the user after the export.
The target folder is in a plm safe, so the file needs to be checked in in order to be used by other people.
Process.Start(targetfolder) doesn't work, because the folder gets opened "dumb" without any of the plm safe functionality.
Process.Start("explorer.exe", targetfolder) opens the folder using the proper safe environment, however it will open a second folder when I run it again. Ideally I would like the folder to only become active if it's already opened.
I found that I could use
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
End Function
...
If FindWindow(vbNullString, IO.Path.GetFileName(targetfolder)) = 0 Then
Process.Start("explorer.exe", targetfolder)
Else
AppActivate(IO.Path.GetFileName(targetfolder))
End If
In order to only open a new window if there isn't one already. However, this also doesn't work reliably, because IO.Path.GetFileName(targetfolder) returns only the folder's name without the entire path. This means that if the user has a folder opened, that has the same name as the target folder but sits in a different spot FindWindow(vbNullString, IO.Path.GetFileName(targetfolder)) will find the other folder to be opened and won't open the target folder. It essentially can't differentiate the two. Additionally, AppActivate(IO.Path.GetFileName(targetfolder)) doesn't work if there are two folders of the same name opened.
Another thing I found was that you cannot rename a directory using FileSystem.Rename() while a child folder of the target folder is opened. I could use this to check if the target folder is opened, by trying to rename the parent folder, however this will create many many false positives.
I am now officially out of ideas. I also cannot use the plm safe's API, because the NX-script doesn't allow the use of "foreign" dll files, such as the plm library.
How do I check if a specific path is already opened in an explorer window?

Taken from here, you could do something along those lines:
Private Function isPathOpenedInExplorer(myPath As String) As Boolean
Dim shellWindows As SHDocVw.ShellWindows = New SHDocVw.ShellWindows()
Dim filename As String
For Each ie As SHDocVw.InternetExplorer In shellWindows
filename = Path.GetFileNameWithoutExtension(ie.FullName).ToLower()
If filename.Equals("explorer") Then
If myPath = ie.LocationURL.Remove(0, 8).Replace("/", "\").Replace("%20", " ") Then
Return True ' Found
End If
End If
Next
Return False 'Not Found
End Function
don't forget to Imports System.IO and Add reference to 'SHDocVw'

Related

Showing the File Extensions inside the folder

Currently, I am working on a feature that will make the files inside the folder that will not hide the file extensions using this code.
Imports Microsoft.Win32
Sub SetNoDrives(value As Integer, path as string)
Dim RegPath As String = "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced]"
Using Key As RegistryKey = Registry.LocalMachine.OpenSubKey(RegPath)
Key.SetValue("HideFileExt", value, RegistryValueKind.DWord)
End Using
End Sub
the problem is, I don't know where to place the string path (folder path) on the code. the path is the specific location where you will always show the file extensions of the files inside the folder.
Any help will be much appreciated.
The reason you don't know where to put the folder path is because there is nowhere to put the folder path. This is a user-wide option, i.e. either extensions are displayed in every folder or no folder for the current user. You don't get to choose on a folder by folder basis. At least, there is no option in Windows/File Explorer to do that and I've never seen mention of it being possible, even when specifically searching for it.

How to get the path of selected folder in vb .net?

I have created a small application in vb .net to load all the files present inside the current folder where my application is running. I want to customize this application in such a manner that, when the user right click on any folder my application name also should appear in that menu. When the user click's that option, all the files present inside that corresponding folder should get listed.
I have achieved this partially. I have added my application to the right click menu item of all folders. But when I click my application name, all the files present in the parent directory is listed. I want to customize my coding to receive the path of the selected folder. So, how to do that?
There's a whole tutorial on MSDN: Verbs and File Associations
For example, the open verb normally launches a program to open a file. The command string typically looks as follows:
"My Program.exe" "%1"
You can get the parameters by the code below:
Public Sub Main(ByVal cmdArgs() As String)
If cmdArgs.Length > 0 Then
'Process the command.
'cmdArgs(0) is program name
'cmdArgs(1) is the path of your folder / file.
End If
End Sub
For Windows Forms, please see this .You'll need a function like below:
Public Sub Main(ByVal cmdArgs() As String)
'Process cmdArgs here (same as above)
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(False)
Application.Run(New Form1)
End Sub

VBA - Relative vs Absolute References to XLAM files

my colleague developed an application contained in an xslm file, which has to be accessible to me as well. The file connects to a lot of xlam libraries which are saved locally on his machine due to speed reasons (loading 30 libraries from a shared drive takes ages).
In order for me to access this application a copy was created on a shared drive, where the libraries were copied as well. When my colleague opens another applications (which references the his local xlam libraries) and then the shared xlsm file in one instance of Excel, the references in the shared file get diverted from the shared xlams to the local xlams, making the shared application dysfunctional to me - I cannot access his local xlams. Can this automatic change of xlam references be prohibited? Is there a way to hard-code paths to xlam references just as one would reference a DLL in VBA?
Any help is much appreciated,
Daniel
These xlam files are addIns.
You should be able to reference them at runtime using the path. Here is an example I found for you on MSDN Blog: Accelerating Things (Loading Excel Add-Ins at Runtime) (you could find this with a Google search)
Private Sub Workbook_Open()
call LoadExternalAddIns
End Sub
Private sub LoadExternalAddIns(optional byval sAddinName as string="")
Dim success As Boolean
Dim myAddIn As AddIn
dim sPath2AddIn as string
'dim sAddinName as string
sPath2AddIn = "c:\myaddins\"
if sAddinName="" then sAddinName="myxlam.xlam"
' Load XLL
'success = Application.RegisterXLL(sPath2AddIn & sAddinName)
' Load and install new XLAM
Set myAddIn = Application.AddIns.Add(sPath2AddIn & sAddinName)
myAddIn.Installed = True
' Load known XLAM
For Each myAddIn In AddIns
If myAddIn.Name = "myknownaddin.xlam" Then
myAddIn.Installed = False
myAddIn.Installed = True
End If
Next
End Sub
Of course, this is just a sample to get you started, in fact as you have lot's of AddIns, you might want to list them on a hidden worksheet then call the above procedure LoadExternalAddIns maybe passing the name for each one in a loop such as call LoadExternalAddIns (sAddInName).
More Resources:
Chip Pearson - Installing An Add-In

Is it possible to specify a location in a user's home directory for a shared library in VBA (in Office for Mac)?

I'm currently using the VBA code similar to the following to specify a location of a shared library for use in communicating (passing a string) from an Office application to a desktop application. The VBA code/macros will need to exist in an add-in (.ppa).
Private Declare Sub sharedLibPassString CDecl Lib "/Users/myUserName/Library/Application Support/myCompanyName/MySharedLib.dylib" Alias "PassString" (ByVal aString As String)
In code from a VBA Macro, I then can do the following.
Call sharedLibPassString(myString)
I've got the communication working, but I'd like to replace the /Users/myUserName/ part with the current user's home directory. Normally on a Mac, you'd specify ~/Library/Application Support/..., but the ~/ syntax doesn't work, producing a "File not found" runtime error.
I discovered that using the following Environment Variable method gets me the ~/ location that I need:
Environ("HOME")
However, I don't see a way to make this part of the CDecl Lib statement, since, as far as I can tell, Environ is evaluated at runtime.
Is there any way to specify a location of a shared library in the user's home directory (~/) in VBA?
Here are a few notes about my environment/approach:
I'm using a Mac, though I believe if there is a solution it would be similar on a PC.
I don't believe it shouldn't matter, but the Office application I'm using is PowerPoint (2011).
The reason I'm trying to access an area inside of the Application Support directory, instead of the default location for shared libraries is because I'd like the Desktop application to place the shared library in a location without an installer, and without requiring a user's or administrator's privileges. If there is a better solution or location to accomplish the same task, this would be very helpful as well.
Sorry for giving a long response, I just wanted to make sure I explained this fairly well.
From this page (Anatomy of a Declare Statement) we read that
The Lib keyword specifies which DLL contains the function. Note that
the name of the DLL is contained in a string within the Declare
statement.
(emphasis added)
From experimentation, the VBE scolds me if I try to give anything but a string constant.
The only work around that I'm aware of requires rewriting the string constant at runtime.
Here is an example of how this could be done: Let's say your delaration statement is in Module1 in your current project, and that you deliberately wrote the declaration in this format at the top of your module:
Private Declare Sub sharedLibPassString CDecl Lib _
"/Users/myUserName/Library/Application Support/myCompanyName/MySharedLib.dylib" _
Alias "PassString" (ByVal aString As String)
You can access that module via code through this (requires permissions to VBA in trust Center listed under Developer Macro Settings):
Dim myModule
set myModule = ActivePresentation.VBProject.VBComponents("Module1").CodeModule
Once you've gained the CodeModule, you can replace the 2nd line directly:
myModule.ReplaceLine 2, Environ("HOME") & " _"
Mission accomplished!
If you do this, you will need to update the path prior to attempting to call your declared sub. There must be a break in execution that allows VBA to recognize the change. Also, you will not be able to modify the code while in break mode.
Now if I were doing this, I'd want to make sure I replace the right line, to not break code. You can check the contents of the 2nd line by calling this myModule.Lines(2,1) which will return the string value of the line.
However, here is a more robust solution that will find the correct line and then replace it (assumes myModule has already been defined as listed above):
Dim SL As Long, EL As Long, SC As Long, EC As Long
Dim Found As Boolean
SL = 1 ' Start on line 1
SC = 1 ' Start on Column 1
EL = 99999 ' Search until the 99999th line
EC = 999 ' Search until the 999th column
With myModule
'If found, the correct line will be be placed in the variable SL
'Broke search string into two pieces so that I won't accidentally find it.
Found = .Find("/Users/myUserName/Library/Application Support/myCompanyName/" & _
"MySharedLib.dylib", SL, SC, EL, EC, True, False, False)
If Found = True Then
'Replace the line with the line you want, second paramater should be a string of the value.
.ReplaceLine SL, Environ("HOME") & " _"
End If
End With
I don't have a Mac, so this is an incomplete answer and I don't know if it will help, but it's a couple of ideas.
I know on Windows, VB doesn't load an external library until you first try to call a function declared with it, and if you specify only the filename in the declare statement, it will use the system path to look for it. Once I did the same thing you are doing, loading a library from a dynamic path, by specifying only a filename, then making a system API call to set the current working directory to the directory of the library before loading it. Changing the PATH environment variable would probably also work.
Second idea: you could hard-code the path to a filename in the /tmp directory; then automatically copy the desired library to that location before loading it. Watch out for the file being in use by another process, but that's only an error if it is a different version of the file to the one that you want.

Protect single file!

I'm trying to protect a folder and the files inside it.
I'm able to protect the folder itself, so that if somebody clicks on it he will get a message:
"You don't currently have permission to access this folder!"
But I can still access files in that folder. For example, if somebody knows the name of a file inside the folder he can type D:\ProtectedFolder\pdffile.pdf and he can open the file!
So, my question is:
Can I protect single files inside the folder?
This is the function that I use for folder lock:
Public Function Lock(ByVal folder As
String, ByVal user As String)
Dim FilePath As String = folder
Dim fs As FileSystemSecurity = File.GetAccessControl(FilePath)
fs.AddAccessRule(New FileSystemAccessRule(user,
FileSystemRights.ListDirectory,
AccessControlType.Deny))
fs.AddAccessRule(New FileSystemAccessRule(user,
FileSystemRights.FullControl,
AccessControlType.Deny))
File.SetAccessControl(FilePath, fs)
Return 0
End Function
Thanks!
You will also have to deny FileSystemRights.Read if you want to prevent that. And technically you have to make sure that the files inherited their rights from the folder.
Specify FileShare.None for File.Open. You can see my C# implementation of it here with full source code. Convert it to VB.NET if you'd like.
This is the message you receive when trying to open a file locked by the application:
I think that's what you're after.