Clipper On Line • Ver Tópico - Chamar APIs do Windows
Página 1 de 1

Chamar APIs do Windows

MensagemEnviado: 10 Nov 2015 10:27
por André Corrêa
Bom dia,

Pesquisei bastante sobre o assunto antes de abrir um novo tópico, mas não encontrei a informação que queria.
Já fiz uso de algumas funções da API do Windows em Delphi para manipular as letras de unidade atribuídas aos discos.
Tenho um aplicativo em Delphi que permite listar e alterar a letra atribuída a um pendrive, por exemplo.
As funções chamadas são "GetVolumeNameForVolumeMountPoint()", "DeleteVolumeMountPoint", "SetVolumeMountPoint()"
e "GetDriveType()".
A questão é que não estou conseguindo chamar essas funções pelo Xailer. Encontrei apenas uma substituta para "GetDriveType",
que seria a "GetDrives()".
Alguém sabe como devo fazer para chamar essas funções? Já tentei colocar todos os headers referentes ao Windows na cláusula
#include, mas a IDE não reconhece as funções.

Obrigado,

André Luiz

Chamar APIs do Windows

MensagemEnviado: 10 Nov 2015 21:02
por fladimir
Se vc tiver elas em C dá pra usar agora se entendi bem chamar as q tem no Delphi talvez através de Dll.

Vou ver aki se acho algo relativo a essas funções e te falo.

Chamar APIs do Windows

MensagemEnviado: 11 Nov 2015 06:45
por André Corrêa
fladimir,

Essas APIs podem ser consultadas aqui https://msdn.microsoft.com/en-us/library/windows/desktop/aa365731(v=vs.85).aspx.
Eu achava que elas poderiam ser invocadas a partir de qualquer linguagem ou IDE sem muito esforço, já que fazem parte do sistema
operacional, mas parece que não é bem assim.
Também não encontrei nenhuma Classe, nem função no Xailer que permita manipular as letras das unidades dessa forma.
Se souber de alguma, me avise, por favor.

Obrigado.

Chamar APIs do Windows

MensagemEnviado: 11 Nov 2015 07:38
por sambomb

Procedure Teste()

   ?GetLogicalDrives()

Return

  DLL32 function GetLogicalDrives();
        AS BOOL PASCAL FROM 'GetLogicalDrives';
        LIB 'kernel32.dll'



Testa assim e vê se vai funcionar

Chamar APIs do Windows

MensagemEnviado: 11 Nov 2015 08:23
por André Corrêa
sambomb,

Fiz o teste, mas acusa "Syntax error "syntax error at 'FUNCTION'" na linha LIB "kernel32.dll".
Vou tentar outros meios. Na verdade, o que queria fazer é simples. Quero alterar a letra de
unidade atribuída pelo Windows a um pendrive, mas sem a necessidade de acessar o gerenciador
de disco. Vou ver se consigo chamar o DISKPART e fazer a alteração via programação.

Obrigado.

Chamar APIs do Windows

MensagemEnviado: 12 Nov 2015 07:33
por sambomb
Pode ser por eu usar Fivewin, verifica comandos semelhantes ae de chamada a DLL

Chamar APIs do Windows

MensagemEnviado: 12 Nov 2015 09:10
por André Corrêa
Bom dia,

Obrigado sambomb, mas descobri que só vai funcionar no Xailer se fizer um wrapper em C destas funções.
Postei a dúvida no fórum do Xailer e o desenvolvedor me enviou uma função que é justamente esse wrapper.
Antes deles responderem, consegui fazer o que queria, mas utilizando o DISKPART em segundo plano e gerando
um script em tempo de execução.

Seguem as funções:

Procedure CriaScript(cDrive, cLetra)  //Cria um script que será lido pelo DISKPART

  Local Arq

  IF !File("C:\bat\DskScript.tmp")  //Checa se o arquivo existe e o cria, sempre vazio
    Arq:=FCreate("C:\bat\DskScript.tmp")
    FClose(Arq)
  ENDIF

  Arq:=FOpen("c:\bat\DskScript.tmp", 2)
  FWRITE(Arq, "SELECT VOLUME "+cDrive+CRLF+"ASSIGN LETTER="+cLetra) //Grava o script com as opções recebidas
  FCLOSE(Arq)

Return


Procedure AlteraLetra()  //Altera a letra do disco removível utilizando o script gerado

  Local oErr

  TRY
    ShellExecute(,"OPEN","DISKPART","/s c:\bat\DskScript.tmp",,0) //Executa o DISKPART passando o script como parâmetro
    MsgAlert("Alteração efetuada com sucesso!")
  CATCH oErr
    MsgAlert("Não foi possível efetuar a alteração!")
    MsgAlert("Erro: " +oErr)
  END 

Return


Function ListaLetras()  //Lista apenas as letras disponíveis

  Local aAlf:={"A:","B:","C:","D:","E:","F:","G:","H:","I:","J:","K:","L:",;
  "M:","N:","O:","P:","Q:","R:","S:","T:","U:","V:","W:","X:","Y:","Z:"}
  Local a01:=GetDrives() //Lista todos os drives para gerar a lista de letras disponíveis
  Local i
  Local nPos
   
  For i:=1 to Len(a01)
    nPos:=AScan(aAlf, a01[i])
    ADel(aAlf, nPos)
  Next

Return aAlf //Retorna apenas as letras disponíveis

Chamar APIs do Windows

MensagemEnviado: 07 Jan 2016 13:17
por André Corrêa
Depois de algum tempo, baseado em códigos que encontrei na internet, consegui desenvolver 2 funções para controlar o serial e a letra de unidade
dos pendrives. Dessa forma é possível contornar o problema do sistema operacional alterar a letra de unidade.
Ao invés de se basear apenas nela para executar alguma rotina no sistema, pode-se utilizar também o serial, que é único e por meio dele,
alterar a letra de unidade em tempo de execução, sem o risco de selecionar o disco errado.

Seguem os códigos de ambas as funções, espero que possa ajudar alguém.

Obter o serial da letra informada:

FUNCTION GetUsbSerial( f1 ) //Retorna o serial da letra informada
//f1 = Letra

LOCAL cDiskNum := "", cRet
LOCAL oDiskDrive, oWMIObjA, oWMIServerA, oWMIDiskDrive,;
oWMIObjA2,oWMIServerA2,oWMILogicalDisk, oLogicalDrive

  TRY
    oWMIObjA := GetActiveObject( "wbemScripting.SwbemLocator" )
  CATCH
    TRY
      oWMIObjA := CreateObject( "wbemScripting.SwbemLocator" )
    CATCH
      MsgAlert( "ERRO ! Nao criou objeto wbemScripting")
    return 0
    END
  END
  oWMIServerA := oWMIObjA:ConnectServer()
  oWMIDiskDrive := oWMIServerA:ExecQuery( "SELECT * FROM Win32_DiskDrive" )

  TRY
   oWMIObjA2 := GetActiveObject( "wbemScripting.SwbemLocator" )
  CATCH
    TRY
      oWMIObjA2 := CreateObject( "wbemScripting.SwbemLocator" )
    CATCH
      MsgAlert( "ERRO ! Nao criou objeto wbemScripting")
    return 0
    END
  END
  oWMIServerA2  := oWMIObjA2:ConnectServer()
  oWMILogicalDisk := oWMIServerA2:ExecQuery( "SELECT * FROM Win32_LogicalDiskToPartition" )

  FOR EACH oLogicalDrive IN oWMILogicalDisk
    IF SubStr(oLogicalDrive:Dependent, AT('"',oLogicalDrive:Dependent )+1,2 ) == f1
      cDiskNum := SubStr(oLogicalDrive:Antecedent, AT('#',oLogicalDrive:Antecedent )+1,1 )
    ENDIF
  NEXT

  FOR EACH oDiskDrive IN oWMIDiskDrive
    IF oDiskDrive:Name == "\\.\PHYSICALDRIVE" + cDiskNum .AND. oDiskDrive:InterfaceType == "USB"
      cRet := oDiskDrive:SerialNumber
    ENDIF
  NEXT

RETURN cRet


Obter a letra do serial informado:

FUNCTION GetUsbLetter( f1 ) //Retorna a letra do serial informado
//f1 = Serial

LOCAL cDiskNum := "", cRet
LOCAL oDiskDrive, oWMIObjA, oWMIServerA, oWMIDiskDrive,;
oWMIObjA2,oWMIServerA2,oWMILogicalDisk, oLogicalDrive

  TRY
    oWMIObjA := GetActiveObject( "wbemScripting.SwbemLocator" )
  CATCH
    TRY
      oWMIObjA := CreateObject( "wbemScripting.SwbemLocator" )
    CATCH
      MsgAlert( "ERRO ! Nao criou objeto wbemScripting")
    return 0
    END
  END
  oWMIServerA := oWMIObjA:ConnectServer()
  oWMIDiskDrive := oWMIServerA:ExecQuery( "SELECT * FROM Win32_DiskDrive" )

  TRY
   oWMIObjA2 := GetActiveObject( "wbemScripting.SwbemLocator" )
  CATCH
    TRY
      oWMIObjA2 := CreateObject( "wbemScripting.SwbemLocator" )
    CATCH
      MsgAlert( "ERRO ! Nao criou objeto wbemScripting")
    return 0
    END
  END
  oWMIServerA2  := oWMIObjA2:ConnectServer()
  oWMILogicalDisk := oWMIServerA2:ExecQuery( "SELECT * FROM Win32_LogicalDiskToPartition" )

  FOR EACH oLogicalDrive IN oWMILogicalDisk
    FOR EACH oDiskDrive IN oWMIDiskDrive
      IF oDiskDrive:SerialNumber == AllTrim(StrTran(f1," ",""))
        cRet:= SubStr(oLogicalDrive:Dependent, AT('"',oLogicalDrive:Dependent )+1,2 )
      ENDIF
    NEXT
  NEXT

RETURN cRet

Chamar APIs do Windows

MensagemEnviado: 16 Jan 2016 19:58
por fladimir
Obrigado por compartilhar André

Chamar APIs do Windows

MensagemEnviado: 15 Fev 2016 17:54
por JoséQuintas
Só pra complementar:
Pra usar API do Windows, eu uso um esquema do Harbour que acho prático.

Exemplo:

https://msdn.microsoft.com/pt-br/library/windows/desktop/ms724295(v=vs.85).aspx

Descrição lá na Microsoft, indicando que está em Kernel32.dll:

BOOL WINAPI GetComputerName(
_Out_ LPTSTR lpBuffer,
_Inout_ LPDWORD lpnSize
);


Equivalente:

#define KERNEL32DLL       "kernel32.dll"

FUNCTION mywin_GetComputerName()

   LOCAL cComputerName := Space(255), nSize := 250

   CallDll( "GetComputerNameA", KERNEL32DLL, @cComputerName, @nSize )
   RETURN cComputerName


Nome da função, aonde está, e os parâmetros. Praticamente igual ao manual da Microsoft.
A exceção, nesta função que peguei como exemplo, é a variável por referência (ponteiro), que precisa ter um tamanho que consiga armazenar o retorno.

Nota: GetComputerNameA, pra usar a versão em Ascii.
adicionar hbmisc.hbc na compilação, e no Harbour 3.2 é CallDll32()

nota2: essas coisas que mencionei tem lá no site:

lpBuffer (out)
A pointer to a buffer that receives the computer name or the cluster virtual server name. The buffer size should be large enough to contain MAX_COMPUTERNAME_LENGTH + 1 characters.
...
GetComputerNameW (Unicode) and GetComputerNameA (ANSI)

Chamar APIs do Windows

MensagemEnviado: 02 Jan 2017 14:33
por rochinha
Amiguinhos,

Ferramenta util para obter as funções e parâmetros das DLLs do Windows.

download