Muryllo Posted January 1, 2016 at 04:58 PM Report Share #591174 Posted January 1, 2016 at 04:58 PM (edited) Boas, feliz ano novo a todos. Começando já este 2016 com um probleminha de programação 😛 ... Estou tendo um problema ao usar a função MoveFileEx para excluir um arquivo no próximo reboot do computador. Eu fiz uma classe básica com funções que eu irei utilizar durante o projeto, mas falta ainda a função de excluir o arquivo após carregar os drivers ou o autochk.exe ser executado. Trata-se de um uninstaller em vb.net. Minha classe é essa : Imports System.IO Imports System.Environment Imports System.Runtime.InteropServices ' Public Class Uninstaller ' <[DllImport]("KERNEL32.DLL", SetLastError:=True, EntryPoint:="MoveFileEx", CharSet:=CharSet.Auto)> _ Public Shared Function MoveFileEx(ByVal lpfilename As String, ByVal lpnewpath As IntPtr, ByVal dwflags As Integer) As Integer End Function ' <[DllImport]("KERNEL32.DLL", SetLastError:=True, EntryPoint:="MoveFileEx", CharSet:=CharSet.Auto)> _ Public Shared Function MoveFileEx(ByVal lpfilename As String, ByVal lpnewpath As String, ByVal dwflags As Integer) As Integer End Function ' <[DllImport]("KERNEL32.DLL", SetLastError:=True, EntryPoint:="DeleteFile", CharSet:=CharSet.Auto)> _ Public Shared Function DeleteFile(ByVal lpfilename As String) As Integer End Function ' <[DllImport]("KERNEL32.DLL", SetLastError:=True, EntryPoint:="RemoveDirectory", CharSet:=CharSet.Auto)> _ Public Shared Function RemoveDirectory(ByVal lpdirectoryname As String) As Integer End Function ' Public Enum MoveFileFlags MOVE_FILE_NULL = &H0 MOVE_FILE_REPLACE_EXISTING = &H1 MOVE_FILE_COPY_ALLOWED = &H2 MOVE_FILE_DELAY_UNTIL_REBOOT = &H4 MOVE_FILE_CREATE_HARDLINK = &H10 MOVE_FILE_FAIL_IF_NOT_TRACKABLE = &H20 End Enum ' Public Shared Function NtSuccess(ByVal Status As Integer) As Boolean Try If Status = &H0 Then Return False Else Return True End If Catch NTSTATUS As Exception Return False End Try End Function ' Public Shared Function Move_File_On_Reboot(ByVal Current_File_Path As String, ByVal New_File_Path As String) As Boolean Try If (NtSuccess(MoveFileEx(Current_File_Path, New_File_Path, MoveFileFlags.MOVE_FILE_DELAY_UNTIL_REBOOT))) = True Then Return True Else Return False End If Catch NTSTATUS As Exception Return False End Try End Function ' Public Shared Function Replace_File_On_Reboot(ByVal File_Path As String, ByVal New_File As String) As Boolean Try Dim File_Path_Base As String = (Path.GetDirectoryName(File_Path) & "\") Dim New_File_Base As String = (Path.GetDirectoryName(New_File) & "\") Dim File_Temp_Base As String = (GetFolderPath(SpecialFolder.CommonApplicationData) & "\") If (Move_File_On_Reboot(New_File, File_Temp_Base & Path.GetFileName(New_File))) = True Then If (Move_File_On_Reboot(File_Path, New_File_Base & Path.GetFileName(New_File))) = True Then If (Move_File_On_Reboot(File_Temp_Base & Path.GetFileName(New_File), File_Path_Base & Path.GetFileName(File_Path))) = True Then Return True Else Return False End If Else Return False End If Else Return False End If Catch NTSTATUS As Exception Return False End Try End Function ' Public Shared Function Delete_File_After_Reboot(ByVal File_Path As String) As Boolean Try If File.Exists(File_Path) = True Then If (NtSuccess(MoveFileEx(File_Path, IntPtr.Zero, MoveFileFlags.MOVE_FILE_DELAY_UNTIL_REBOOT))) = True Then Return True Else Return False End If Else Return False End If Catch NTSTATUS As Exception Return False End Try End Function ' Public Shared Function Delete_File(ByVal File_Path As String) As Boolean Try If (File.Exists(File_Path)) = True Then If (NtSuccess(DeleteFile(File_Path))) = True Then Return True Else If (Delete_File_After_Reboot(File_Path)) = True Then Return True Else Return False End If End If Else Return False End If Catch NTSTATUS As Exception Return False End Try End Function ' Public Shared Function Delete_Directory(ByVal Directory_Path As String) As Boolean Try If (Directory.Exists(Directory_Path)) = True Then If (NtSuccess(RemoveDirectory(Directory_Path))) = True Then Return True Else If (NtSuccess(MoveFileEx(Directory_Path, IntPtr.Zero, MoveFileFlags.MOVE_FILE_DELAY_UNTIL_REBOOT))) = True Then Return True Else Return False End If End If Else Return False End If Catch NTSTATUS As Exception Return False End Try End Function ' Public Shared Function Delete_All_Files(ByVal Directory_Path As String) As Boolean Try If (Directory.Exists(Directory_Path)) = True Then Dim Directory_Info As DirectoryInfo = New DirectoryInfo(Directory_Path) For Each Current_File_Info As FileInfo In Directory_Info.GetFiles("*.*", SearchOption.TopDirectoryOnly) Delete_File(Current_File_Info.FullName) Next For Each New_Directory_Info As DirectoryInfo In Directory_Info.GetDirectories() Delete_All_Files(New_Directory_Info.FullName) Next Return True Else Return False End If Catch NTSTATUS As Exception Return False End Try End Function ' Public Shared Function Delete_All_Directories(ByVal Directory_Path As String) As Boolean Try If (Directory.Exists(Directory_Path)) = True Then Dim Directory_Info As DirectoryInfo = New DirectoryInfo(Directory_Path) For Each Current_Directory_Info As DirectoryInfo In Directory_Info.GetDirectories("*.*", SearchOption.TopDirectoryOnly) Delete_All_Directories(Current_Directory_Info.FullName) Delete_Directory(Current_Directory_Info.FullName) Next Delete_Directory(Directory_Path) Return True Else Return False End If Catch NTSTATUS As Exception Return False End Try End Function ' Public Shared Function Uninstall(ByVal Directory_Path As String) As Boolean Try If (Directory.Exists(Directory_Path)) = True Then If (Delete_All_Files(Directory_Path)) = True Then If (Delete_All_Directories(Directory_Path)) = True Then Return True Else Return False End If Else Return False End If Else Return False End If Catch NTSTATUS As Exception Return False End Try End Function ' End Class O problema é o seguinte, toda essa classe aí está funcionando ok, porém eu tentei criar a função de exclusão no reboot que de acordo com a MSDN é : MoveFileEx(CAMINHO_DO_ARQUIVO, NULL, 0x00000004); Porém a função está retornando algo bem inesperado hahaha ... Ela entende definitivamente que o 0 "NULL" é o nome do arquivo a ser posto no novo diretório e ele move o arquivo do diretório atual para o diretório base da aplicação que chama a função e põe o nome 0... Alguém conhece uma forma de corrigir isso ? Obrigado e Feliz ano novo mais uma vez ^^ Edited January 5, 2016 at 01:38 PM by Muryllo Link to comment Share on other sites More sharing options...
He B TeMy Posted January 1, 2016 at 05:10 PM Report Share #591175 Posted January 1, 2016 at 05:10 PM O caminho que estás a passar é o caminho completo de um ficheiro? Já experimentas-te ver se a função retorna erro? A aplicação que estás a correr esse código está como administrador? Link to comment Share on other sites More sharing options...
Muryllo Posted January 1, 2016 at 08:42 PM Author Report Share #591182 Posted January 1, 2016 at 08:42 PM (edited) O caminho é completo a função não retorna 0 e ele roda como administrador. Só que o arquivo é movido para o diretório da aplicação com o nome "0". Estou tentando desta forma : Public Shared Function Delete_File_After_Reboot(ByVal File_Path As String) As Boolean Try If File.Exists(File_Path) = True Then If (NtSuccess(MoveFileEx(File_Path, 0, MoveFileFlags.MOVE_FILE_DELAY_UNTIL_REBOOT))) = True Then Return True Else Return False End If Else Return False End If Catch NTSTATUS As Exception Return False End Try End Function Edited January 1, 2016 at 09:28 PM by Muryllo Link to comment Share on other sites More sharing options...
Solution He B TeMy Posted January 1, 2016 at 11:22 PM Solution Report Share #591185 Posted January 1, 2016 at 11:22 PM Muda a assinatura da função deste parametro: ByVal lpnewpath As String para ByVal lpnewpath As IntPtr E passa IntPtr.Zero em vez de '0' quando chamas a função. 1 Report Link to comment Share on other sites More sharing options...
Muryllo Posted January 2, 2016 at 12:28 AM Author Report Share #591187 Posted January 2, 2016 at 12:28 AM (edited) Perfeito ... A função retorna 0x00000001 (TRUE) e os dois últimos bytes da trilha lpnewpath são escritos com 0 (NULL). O sistema agora reconhece e exclui o arquivo. Obrigado pela ajuda, a classe ficou assim : Imports System.IO Imports System.Environment Imports System.Runtime.InteropServices ' Public Class Uninstaller ' <[DllImport]("KERNEL32.DLL", SetLastError:=True, EntryPoint:="MoveFileEx", CharSet:=CharSet.Auto)> _ Public Shared Function MoveFileEx(ByVal lpfilename As String, ByVal lpnewpath As IntPtr, ByVal dwflags As Integer) As Integer End Function ' <[DllImport]("KERNEL32.DLL", SetLastError:=True, EntryPoint:="MoveFileEx", CharSet:=CharSet.Auto)> _ Public Shared Function MoveFileEx(ByVal lpfilename As String, ByVal lpnewpath As String, ByVal dwflags As Integer) As Integer End Function ' <[DllImport]("KERNEL32.DLL", SetLastError:=True, EntryPoint:="DeleteFile", CharSet:=CharSet.Auto)> _ Public Shared Function DeleteFile(ByVal lpfilename As String) As Integer End Function ' <[DllImport]("KERNEL32.DLL", SetLastError:=True, EntryPoint:="RemoveDirectory", CharSet:=CharSet.Auto)> _ Public Shared Function RemoveDirectory(ByVal lpdirectoryname As String) As Integer End Function ' Public Enum MoveFileFlags MOVE_FILE_NULL = &H0 MOVE_FILE_REPLACE_EXISTING = &H1 MOVE_FILE_COPY_ALLOWED = &H2 MOVE_FILE_DELAY_UNTIL_REBOOT = &H4 MOVE_FILE_CREATE_HARDLINK = &H10 MOVE_FILE_FAIL_IF_NOT_TRACKABLE = &H20 End Enum ' Public Shared Function NtSuccess(ByVal Status As Integer) As Boolean Try If Status = &H0 Then Return False Else Return True End If Catch NTSTATUS As Exception Return False End Try End Function ' Public Shared Function Move_File_On_Reboot(ByVal Current_File_Path As String, ByVal New_File_Path As String) As Boolean Try If (NtSuccess(MoveFileEx(Current_File_Path, New_File_Path, MoveFileFlags.MOVE_FILE_DELAY_UNTIL_REBOOT))) = True Then Return True Else Return False End If Catch NTSTATUS As Exception Return False End Try End Function ' Public Shared Function Replace_File_On_Reboot(ByVal File_Path As String, ByVal New_File As String) As Boolean Try Dim File_Path_Base As String = (Path.GetDirectoryName(File_Path) & "\") Dim New_File_Base As String = (Path.GetDirectoryName(New_File) & "\") Dim File_Temp_Base As String = (GetFolderPath(SpecialFolder.CommonApplicationData) & "\") If (Move_File_On_Reboot(New_File, File_Temp_Base & Path.GetFileName(New_File))) = True Then If (Move_File_On_Reboot(File_Path, New_File_Base & Path.GetFileName(New_File))) = True Then If (Move_File_On_Reboot(File_Temp_Base & Path.GetFileName(New_File), File_Path_Base & Path.GetFileName(File_Path))) = True Then Return True Else Return False End If Else Return False End If Else Return False End If Catch NTSTATUS As Exception Return False End Try End Function ' Public Shared Function Delete_File_After_Reboot(ByVal File_Path As String) As Boolean Try If File.Exists(File_Path) = True Then If (NtSuccess(MoveFileEx(File_Path, IntPtr.Zero, MoveFileFlags.MOVE_FILE_DELAY_UNTIL_REBOOT))) = True Then Return True Else Return False End If Else Return False End If Catch NTSTATUS As Exception Return False End Try End Function ' Public Shared Function Delete_File(ByVal File_Path As String) As Boolean Try If (File.Exists(File_Path)) = True Then If (NtSuccess(DeleteFile(File_Path))) = True Then Return True Else If (Delete_File_After_Reboot(File_Path)) = True Then Return True Else Return False End If End If Else Return False End If Catch NTSTATUS As Exception Return False End Try End Function ' Public Shared Function Delete_Directory(ByVal Directory_Path As String) As Boolean Try If (Directory.Exists(Directory_Path)) = True Then If (NtSuccess(RemoveDirectory(Directory_Path))) = True Then Return True Else If (NtSuccess(MoveFileEx(Directory_Path, IntPtr.Zero, MoveFileFlags.MOVE_FILE_DELAY_UNTIL_REBOOT))) = True Then Return True Else Return False End If End If Else Return False End If Catch NTSTATUS As Exception Return False End Try End Function ' Public Shared Function Delete_All_Files(ByVal Directory_Path As String) As Boolean Try If (Directory.Exists(Directory_Path)) = True Then Dim Directory_Info As DirectoryInfo = New DirectoryInfo(Directory_Path) For Each Current_File_Info As FileInfo In Directory_Info.GetFiles("*.*", SearchOption.TopDirectoryOnly) Delete_File(Current_File_Info.FullName) Next For Each New_Directory_Info As DirectoryInfo In Directory_Info.GetDirectories() Delete_All_Files(New_Directory_Info.FullName) Next Return True Else Return False End If Catch NTSTATUS As Exception Return False End Try End Function ' Public Shared Function Delete_All_Directories(ByVal Directory_Path As String) As Boolean Try If (Directory.Exists(Directory_Path)) = True Then Dim Directory_Info As DirectoryInfo = New DirectoryInfo(Directory_Path) For Each Current_Directory_Info As DirectoryInfo In Directory_Info.GetDirectories("*.*", SearchOption.TopDirectoryOnly) Delete_All_Directories(Current_Directory_Info.FullName) Delete_Directory(Current_Directory_Info.FullName) Next Delete_Directory(Directory_Path) Return True Else Return False End If Catch NTSTATUS As Exception Return False End Try End Function ' Public Shared Function Uninstall(ByVal Directory_Path As String) As Boolean Try If (Directory.Exists(Directory_Path)) = True Then If (Delete_All_Files(Directory_Path)) = True Then If (Delete_All_Directories(Directory_Path)) = True Then Return True Else Return False End If Else Return False End If Else Return False End If Catch NTSTATUS As Exception Return False End Try End Function ' End Class Abraços. Edited January 5, 2016 at 01:39 PM by Muryllo Link to comment Share on other sites More sharing options...
He B TeMy Posted January 2, 2016 at 12:46 AM Report Share #591188 Posted January 2, 2016 at 12:46 AM (edited) Porque é que tens duas assinaturas da mesma função? E porque é que usas a propriedade 'EntryPoint' se lhe vais dar o mesmo nome? Eu também perguntava porque tens esse código cheio de try-catchs, mas como já o fiz numas perguntas tuas anteriores e tu não deste ouvidos não me dou ao trabalho 😉 Edited January 2, 2016 at 01:11 AM by He B TeMy Link to comment Share on other sites More sharing options...
Muryllo Posted January 2, 2016 at 01:09 AM Author Report Share #591189 Posted January 2, 2016 at 01:09 AM O Visual Basic aceita duas assinaturas desde que não sejam idênticas. Eu uso as duas pois tem funções que necessitam passar string em lpnewpath e a outra de excluir no reboot necessita passar NULL (0). Sempre deixo meus códigos cheio de try catchs, eles não atrapalham o desempenho e não custa nada usá-los, não gosto de código a solta e odeio alertas JIT, eu evito isso ao máximo mas ok as vezes eu exagero. Link to comment Share on other sites More sharing options...
He B TeMy Posted January 2, 2016 at 01:15 AM Report Share #591190 Posted January 2, 2016 at 01:15 AM Duas assinaturas da mesma função não faz muito sentido, mas se não tens problema eu também não. Usares try catch aí simplesmente não faz nada, se enches o teu código de try-catchs sem razão e fazes catch 'NTSTATUS' como se isso fosse algum erro que tu pudesses apanhar... mas pronto, como disse, já referi isso noutros threads teus, não o vou referir mais. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now