LAS APIS COPYFILE Y SHELLEXECUTE, Y SUS EQUIVALENTES EN .NET CON C#

 

Después de mucho programar Apis en Visual Basic 6, se me hizo difícil dejar esa costumbre al pasar al C Sharp. Con la plataforma .Net,  ya no son necesarias muchas de las llamadas a Apis, pero dado que el Visual Basic 6 está tan bien documentado suele ser más sencillo hallar en internet cómo hacer algo usando una Api que usando .Net. Lo malo: llamar a las apis hace depender nuestras aplicaciones del sistema operativo Windows.  


Con ShellExecute para C Sharp:

En .Net tenemos la clase Process que hace todo lo que hace la api ShellExecute así que no tendríamos porqué necesitarla más. Por ejemplo, para ejecutar un programa, se pone:

Process p = new Process();
p.StartInfo.FileName = "iexplore.exe";
p.StartInfo.Arguments = "http://www.microsoft.com";
p.Start();


o abrir el Notepad:

Process p = new Process();
p.StartInfo.FileName = "notepad.exe";
p.Start();


Si quiero abrir un archivo el código sería:

Process pr = new Process();
try
{

pr.StartInfo.FileName = @"C:\un_archivo_cualquiera";
pr.Start();
}
catch (NullReferenceException ex)
{
MessageBox.Show(ex.Message, "Error");
}


Que reemplaza a este otro código (dentro de una clase):

class executeIt {

/*
Public Declare Function ShellExecute _
Lib "shell32.dll" _
Alias "ShellExecuteA" ( _
ByVal hwnd As Long, _
ByVal lpOperation As String, _
ByVal lpFile As String, _
ByVal lpParameters As String, _
ByVal lpDirectory As String, _
ByVal nShowCmd As Long) _
As Long
*/

[System.Runtime.InteropServices.DllImport("shell32.dll", EntryPoint = "ShellExecute")]
public static extern int ShellExecuteA(int hwnd, string 
lpOperation, string lpFile, string lpParameters, string lpDirectory,
int nShowCmd); 
}


Lo que está comentado es la llamada a la api para Visual Basic 6, debajo está la "traducción" para C Sharp. Así se puede ir deduciendo cómo "traducir" el código que llama apis para VB6 a C Sharp.

Para usar la api se hace:

executeIt.ShellExecuteA(0, "OPEN","E:\\mundodisco_1-27.zip","", "", 0);
executeIt.ShellExecuteA(0, "OPEN","F:\\Músi-k","", "", 1);


La primera línea abre mis libros zipeados del Mundodisco de Terry Pratchett. La segunda abre mi carpeta con mis mp3 descargados (y de paso dejo información sobre las particiones de mi disco duro).

Si en Visual Basic 6 las variables se declaraban como Long, en C Sharp su equivalente es el Int. Esto es debido a cuántos bytes ocupan estas variables en cada lenguaje. En esta página se puede ver una comparación de los tipos de variables, su tamaño y otras características.


Usando la api CopyFile:

Si se compila el siguiente código:

using System;

using System.Collections.Generic;

using System.Text;

namespace ConsoleApplication1

{

class Program

{

/* Public Declare Function CopyFile Lib "kernel32.dll" Alias

* "CopyFileA" (ByVal lpExistingFileName As String,

* ByVal lpNewFileName As String, ByVal bFailIfExists As Long) As Long

*/

[System.Runtime.InteropServices.DllImport("kernel32.dll", EntryPoint = "CopyFile")]

public static extern int CopyFileA(string lpExistingFileName, string

lpNewFileName, int bFailIfExists);

 

private void replicar() {

int count, rad;

string copia = " ";

 

string nombre_archivo = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;

// Fuente: http://blogs.msdn.com/brada/archive/2004/04/14/113620.aspx  por Luc Cluitmans

 

count = 0;

System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(@"C:\");

foreach (System.IO.FileInfo file in dir.GetFiles("CopyIt*.exe"))

count++; // si es cero es que no existe el archivo.

for (int i = count; i <= count * 2+1; i++)

{

copia = String.Concat("C:\\", "CopyIt", i.ToString(), ".exe");

rad = CopyFileA(nombre_archivo, copia, 0);

}

}

 

static void Main(string[] args)

{ Program pp = new Program();

pp.replicar();

}

}

}

se tendrá un programa que simplemente busca cuántas copias existen en C:\ (los archivitos "CopyIt*.exe") y luego con un bucle se copia el doble de veces más uno. No interesa cómo se llame el programa original o dónde se encuentre, siempre sus copias terminarán en C:\ y siempre contará cuántas de ellas existen. Así, después de unos pocos clicks, el disco duro (poniendo el ícono apropiado) se verá así:


 

Y como todos son el mismo programa, se puede ejecutar cualquiera de ellos y harán lo mismo: copiarse y copiarse.


Y ahora, su equivalente para .Net:

using System;

using System.Collections.Generic;

using System.Text;

using System.IO;

namespace ConsoleApplication1

{

class Program

{

private void replicar() {

int count;

string copia = " ";

string nombre_archivo = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;

// Fuente: http://blogs.msdn.com/brada/archive/2004/04/14/113620.aspx  por Luc Cluitmans

 

count = 0;

DirectoryInfo dir = new DirectoryInfo(@"C:\");

foreach (FileInfo file in dir.GetFiles("CopyIt*.exe"))

count++; // si es cero es que no existe el archivo.

for (int i = count; i <= count * 2+1; i++)

{

copia = String.Concat("C:\\", "CopyIt", i.ToString(), ".exe");

File.Copy(nombre_archivo, copia);

}

}

 

static void Main(string[] args)

{ Program pp = new Program();

pp.replicar();

}

}

}

Si se usan las rutas al estilo Visual basic en C Sharp se debe poner una arroba antes para indicarle que es una ruta de directorio, pues el formato de las rutas a los directorios es:

Rutas de archivos en Visual Basic: por ejemplo: "c:\mi archivo"
Rutas de archivos en C, C++ y C Sharp: por ejemplo: "c:\\mi archivo"