高分求助:C#中如何调用UpdateResource这个API函数!

作者&投稿:汤叛 (若有异议请与网页底部的电邮联系)
c#中如何调用API函数~

一、调用格式
using System.Runtime.InteropServices; //引用此名称空间,简化后面的代码
...
//使用DllImportAttribute特性来引入api函数,注意声明的是空方法,即方法体为空。
[DllImport("user32.dll")]
public static extern ReturnType FunctionName(type arg1,type arg2,...);
//调用时与调用其他方法并无区别

可以使用字段进一步说明特性,用逗号隔开,如:
[ DllImport( "kernel32", EntryPoint="GetVersionEx" )]
DllImportAttribute特性的公共字段如下:
1、CallingConvention 指示向非托管实现传递方法参数时所用的 CallingConvention 值。
CallingConvention.Cdecl : 调用方清理堆栈。它使您能够调用具有 varargs 的函数。
CallingConvention.StdCall : 被调用方清理堆栈。它是从托管代码调用非托管函数的默认约定。
2、CharSet 控制调用函数的名称版本及指示如何向方法封送 String 参数。
此字段被设置为 CharSet 值之一。如果 CharSet 字段设置为 Unicode,则所有字符串参数在传递到非托管实现之前都转换成 Unicode 字符。这还导致向 DLL EntryPoint 的名称中追加字母“W”。如果此字段设置为 Ansi,则字符串将转换成 ANSI 字符串,同时向 DLL EntryPoint 的名称中追加字母“A”。大多数 Win32 API 使用这种追加“W”或“A”的约定。如果 CharSet 设置为 Auto,则这种转换就是与平台有关的(在 Windows NT 上为 Unicode,在 Windows 98 上为 Ansi)。CharSet 的默认值为 Ansi。CharSet 字段也用于确定将从指定的 DLL 导入哪个版本的函数。CharSet.Ansi 和 CharSet.Unicode 的名称匹配规则大不相同。对于 Ansi 来说,如果将 EntryPoint 设置为“MyMethod”且它存在的话,则返回“MyMethod”。如果 DLL 中没有“MyMethod”,但存在“MyMethodA”,则返回“MyMethodA”。对于 Unicode 来说则正好相反。如果将 EntryPoint 设置为“MyMethod”且它存在的话,则返回“MyMethodW”。如果 DLL 中不存在“MyMethodW”,但存在“MyMethod”,则返回“MyMethod”。如果使用的是 Auto,则匹配规则与平台有关(在 Windows NT 上为 Unicode,在 Windows 98 上为 Ansi)。如果 ExactSpelling 设置为 true,则只有当 DLL 中存在“MyMethod”时才返回“MyMethod”。

下面是一个简单的例子,调用API实现了禁用关闭按钮的功能

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace winFormTest
{
public partial class Form2 : Form
{
[DllImport("USER32.DLL")]
public static extern int GetSystemMenu(int hwnd, int bRevert);
[DllImport("USER32.DLL")]
public static extern int RemoveMenu(int hMenu, int nPosition, int wFlags);

const int MF_REMOVE = 0x1000;

const int SC_RESTORE = 0xF120; //还原
const int SC_MOVE = 0xF010; //移动
const int SC_SIZE = 0xF000; //大小
const int SC_MINIMIZE = 0xF020; //最小化
const int SC_MAXIMIZE = 0xF030; //最大化
const int SC_CLOSE = 0xF060; //关闭

public Form2()
{
InitializeComponent();
}

private void Form2_Load(object sender, EventArgs e)
{
int hMenu;
hMenu = GetSystemMenu(this.Handle.ToInt32(), 0);
RemoveMenu(hMenu, SC_CLOSE, MF_REMOVE);
}

}
}

函数原型:BOOL UpdateResource(HANDLE hUpdate,LPCTSTR lPTyPe,LPCTSTR IPName,WORD wLanguage,LPVOID lgData,DWORD cbData);

参数:

hUpdate:指定更新文件句柄。此句柄由BeginUpdateResource函数返回。

lpType:指向说明将被更新的资源类型的字符串,它以NULL为终止符。这个参数可以是一个通过宏MAKENTRESOURCE传递的整数值,含义参见EnumResLangProc\lpType。

lpName:指向说明待被更新的资源名称的字符串,它以NULL为终止符。这个参数可以是一个通过宏MAKEINTRESOURCE传递的整数值。

wLanguage:指定将被更新资源的语言标识。要了解基本的语言标识符以及由这些标识符组成的字语言标识符的列表,可参见宏MAKELANGID。

lpData:指向被插入可执行文件的资源数据的指针。如果资源是预定义类型值之一,那么数据必须是有效且适当排列的。注意这是存储在可执行文件中原始的一进制数据,而不是由Loadlcon,LoadString或其他装载特殊资源函数提供的数据。所有包含字符串、文本的数据必须是Unicode格式;IpData不能指向ANSI数据。

如果lpData为NULL,所指定的资源将从可执行文件中被删除。

cbData:指定lpData中的资源数据数据大小,以字节计数。

返回值:如果函数运行成功,返回值为非零;如果函数运行失败,返回值为零。若想获得更多的错误信息,请调用GetLastError函数。

注意:应用程序重复使用UpdateResource去改变资源数据。每次UpdateResource调用都要占用系统内部的一个增加、删除、替代的列表,而实际上并没有将数据写到可执行文件中。应用程序必须通过使用EndUpdateResource函数将每次积累的变化写入可执行文件中。

建一个Win32函数的工具类如下:
public static class Win32Api
{
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr BeginUpdateResource(string pFileName, [MarshalAs(UnmanagedType.Bool)]bool bDeleteExistingResources);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool UpdateResource(IntPtr hUpdate, string lpType, string lpName, ushort wLanguage, IntPtr lpData, uint cbData);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool EndUpdateResource(IntPtr hUpdate, bool fDiscard);
}

然后像C#方法一样调用就行了。
比如:(示意代码,未验证)

string fileName = @"XXX\XXX.xxx";
// 获得资源句柄
IntPtr hResource = Win32Api.BeginUpdateResource(fileName, false);
if (hResource.ToInt32() == 0) {
throw new Win32Exception(Marshal.GetLastWin32Error());
}
string fileToUpdate = @"YYY\YYY.yyy";
// 累积更新
if (Win32Api.UpdateResource(hResource, "FILE", fileToUpdate, 0, null, 0) == false) {
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
// 写入更新
if (Win32Api.EndUpdateResource(hResource, false) == false) {
throw new Win32Exception(Marshal.GetLastWin32Error());
}

简单,我要实现修改EXE文件图标的功能,须要用于如下函数。
BeginUpdateResource
UpdateResource
EndUpdateResource

其中UpdateResource我不会用。函数原型如下。
-----------------------------
函数功能:该函数增加,删除,或替代某可执行文件中的资源。

函数原型:BOOL UPdateResource(HANDLE hUpdate,LPCTSTR lPTyPe,LPCTSTR IPName,WORD wLanguage,LPVOID lgData,DWORD cbData);

参数:

hUpdate:指定更新文件句柄。此句柄由BeginUpdateResource函数返回。

lpType:指向说明将被更新的资源类型的字符串,它以NULL为终止符。这个参数可以是一个通过宏MAKENTRESOURCE传递的整数值,含义参见EnumResLangProc\lpType。

lpName:指向说明待被更新的资源名称的字符串,它以NULL为终止符。这个参数可以是一个通过宏MAKEINTRESOURCE传递的整数值。

wLanguage:指定将被更新资源的语言标识。要了解基本的语言标识符以及由这些标识符组成的字语言标识符的列表,可参见宏MAKELANGID。

lpData:指向被插入可执行文件的资源数据的指针。如果资源是预定义类型值之一,那么数据必须是有效且适当排列的。注意这是存储在可执行文件中原始的一进制数据,而不是由Loadlcon,LoadString或其他装载特殊资源函数提供的数据。所有包含字符串、文本的数据必须是Unicode格式;IpData不能指向ANSI数据。

如果lpData为NULL,所指定的资源将从可执行文件中被删除。

cbData:指定lpData中的资源数据数据大小,以字节计数。

返回值:如果函数运行成功,返回值为非零;如果函数运行失败,返回值为零。若想获得更多的错误信息,请调用GetLastError函数。

注意:应用程序重复使用UpdateResource去改变资源数据。每次UpdateResource调用都要占用系统内部的一个增加、删除、替代的列表,而实际上并没有将数据写到可执行文件中。应用程序必须通过使用EndUpdateResource函数将每次积累的变化写入可执行文件中。
------------------------------
这是C的函数原型,在C#中用什么表示呀?
请大家给我写出完整代码(从打开到写入完成),在此先谢过啦!

如果有其它的简单实现方法也可以写出来。
问题补充:看清题目(用C#实现),如果谁能做出来,多少分我都给,反正我不想用百度知道了!

建一个Win32函数的工具类如下:
public static class Win32Api
{
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr BeginUpdateResource(string pFileName, [MarshalAs(UnmanagedType.Bool)]bool bDeleteExistingResources);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool UpdateResource(IntPtr hUpdate, string lpType, string lpName, ushort wLanguage, IntPtr lpData, uint cbData);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool EndUpdateResource(IntPtr hUpdate, bool fDiscard);
}

然后像C#方法一样调用就行了。
比如:(示意代码,未验证)

string fileName = @"XXX\XXX.xxx";
// 获得资源句柄
IntPtr hResource = Win32Api.BeginUpdateResource(fileName, false);
if (hResource.ToInt32() == 0) {
throw new Win32Exception(Marshal.GetLastWin32Error());
}
string fileToUpdate = @"YYY\YYY.yyy";
// 累积更新
if (Win32Api.UpdateResource(hResource, "FILE", fileToUpdate, 0, null, 0) == false) {
throw new Win32Exception(Marshal.GetLastWin32Error());
}
}
// 写入更新
if (Win32Api.EndUpdateResource(hResource, false) == false) {
throw new Win32Exception(Marshal.GetLastWin32Error());

找了个例子
function TFormMain.ReplaceMediaRes(SrcFileName:String;MediaFileName:String):Boolean;
var
fs:TFileStream;
buffer:PChar;
hUpdateRes:THandle;
begin
result:=false;
if not FileExists(SrcFileName) then begin
MessageBox(Handle,pchar(SrcFileName+' not exists.'),pchar(Application.Title),MB_ICONERROR);
exit;
end;
if not (FileExists(MediaFileName)) then begin
MessageBox(Handle,pchar(MediaFileName+' not exists.'),pchar(Application.Title),MB_ICONERROR);
exit;
end;
fs:=TFileStream.Create(MediaFileName,fmOpenReadWrite);
try
GetMem(buffer,fs.size);
try
fs.ReadBuffer(buffer^,fs.size);
//begin update resource
hUpdateRes:=BeginUpdateResource(pchar(SrcFileName),false);
if(hUpdateRes=0) then begin
MessageBox(Handle,pchar('Error to begin update resource.'),pchar(Application.Title),MB_ICONERROR);
exit;
end;
//!! the language id can get with GetUserDefaultLangID(), in english system it's 1033.
result:=UpdateResource(hUpdateRes,pchar('PLAYER'),pchar('MEDIA'),1033,buffer,fs.Size);
if not result then begin
MessageBox(Handle,pchar('Error ro update resource'),pchar(Application.Title),MB_ICONERROR);
exit;
end;
if not EndUpdateResource(hUpdateRes,false) then begin
MessageBox(Handle,pchar('Error to end update resource.'),pchar(Application.Title),MB_ICONERROR);
exit;
end;
finally
FreeMem(buffer);
end;
finally
fs.Free;
end;
result:=true;
end;

分太少,加到500分的话可以考虑。


C语言作业求助,十分感谢
C代码和运行结果如下:输如10个数,成功输出了它们的最大值、最小值和平均值,望采纳~附源码:include <stdio.h> int main() { int max, min, sum, num, i;scanf("%d", &num); \/\/ 先输入一1个数 max = min = sum = num;for (i = 0; i < 9; i++) { \/\/ 再输入剩下9...

c语言求助 输入n个学生的考试成绩,求出其中最高分、最低分以及超过平均...
分别表示最高分 最低分 超过平均分人数int main(){ int *redata=NULL; STD *stdHead=(STD *)malloc(sizeof(STD)); stdHead->next=NULL; STD *stdTail=NULL; do{ stdTail=insertScore(stdHead,stdTail); }while(stdTail); printfSTD(stdHead); redata=tjSTD...

C语言程序求助
5.求学生成绩的最高分;6.并计算该班级学生的总分和平均成绩并显示,规则:负分数和100分以上显示“错误”的分数不计数总分及平均成绩计算中;程序结束界面输出。*\/#include "stdio.h"#include "math.h"#include "string.h"void inquire_Num();void init_Cls();void inset_Grade();struct score{...

高分求助:C#中如何调用UpdateResource这个API函数!
函数原型:BOOL UpdateResource(HANDLE hUpdate,LPCTSTR lPTyPe,LPCTSTR IPName,WORD wLanguage,LPVOID lgData,DWORD cbData);参数:hUpdate:指定更新文件句柄。此句柄由BeginUpdateResource函数返回。lpType:指向说明将被更新的资源类型的字符串,它以NULL为终止符。这个参数可以是一个通过宏MAKENTRE...

C语言习题求助,编译通过,运行错误,高分求解
你可以参考我下面提供的类型,希望能够对你有些帮助。Warning 警告类型错误有很多种。例如:(1)、虽然定义了某个变量,但是没有对其是否成功初始化就使用、(2)、把赋值符号的等于(=)写成了逻辑相等(==),等等。例如对于(1)而言:include <stdlib.h> \/* malloc( ) 函数原型在此头文件中...

高分求助,懂机器人C语言的进,
做简单的控制系统很简单,你先学单片机,C语言,和ARDUINO ,就可以制作简单的机器人了,祝你好运 为证明我所言非虚我上两张图 这就是我的工作室,图中已经有一个6足机器人了 PS:那不能称作真正的机器人,机器人应该定义为循环于人类新开辟的物质圈的一种新的物种才对 纯手打,求采纳 ...

求助c类网络的划分问题。
分8个子网,需要借4位,也就是分2^4-2=14个子网。每个子网的主机数为2^4-2=14,地址块大小为:256-240=16 第一个子网的网络号为:192.168.323.16\/28 地址范围:192.168.323.17\/28 - 192.168.323.30\/28 广播地址为:192.168.323.31\/28 第二个子网的网络号为:192.168.323.32\/28...

紧急求助! C语言中常用语句有哪几种?请分别举一例
C语言的关键字分为以下几类:(1)描述类型定义:typedef,void (2)描述存储类型:auto,extern,static,register (3)描述数据类型:char,float,double,int, long,shourt,struct, union,unsigned,const,enum,signed,bolatile (4)描述语句: break,continue,switch,case,default,if,else, do,for,whi...

C语言求助。
include <stdio.h>#include <stdlib.h>#include #include <string.h>#define N 30typedef struct{char name[20];char No[20];char sex[20];float score[5];float avg;}STUDENT;void sort(STUDENT* s) \/\/按平均成绩由高到低排序 {STUDENT t;int i,j;for(i=0;i<N-1;i++){for(j...

C语言作业求助,谢谢
你可以使用如下代码来求解5 * 5矩阵外圈数据的和:在上面的代码中,我们定义了一个5 * 5的矩阵,然后使用四个循环分别求出矩阵的第一行,最后一行,第一列和最后一列的和。最后,我们把所有求出来的和相加,就得到了矩阵外圈元素的和。include <stdio.h>int main(){\/\/ 定义5*5的矩阵(二维数组...

浪卡子县17328455029: C#中UPDATE的用法 -
蓟宝开胸: 尽量不要用这种字符串拼接的方式可以,这样的代码可读性太差了:我一般这样写,一般不会出错……其实你可以抛出一下异常,看看错在哪里了…… try {strsqlUpdate="update tableName set column1=@P1,column2=P2";SqlCommand ...

浪卡子县17328455029: c#连接Oracle求助 -
蓟宝开胸: 你没有添加System.Data命名空间的引用吧?那就用全名: if (con.State == System.Data.

浪卡子县17328455029: c#中如何使用sql updata语句 -
蓟宝开胸: 1.using中引用sqlclient等命名空间2. 打开sqlconnect 对象,用数据库连接字符串初始化3.用sqlconnect对象初始化一个sqlcommand对象4.sqlcommand对象有一系列的运行sql 语句的命令,方法,和属性 给你个例子://SQL非查询语句 public ...

浪卡子县17328455029: C#直接在中修改数据库中的内容,并更新到数据库 用da.Update这个做还有dataadapter -
蓟宝开胸: 1.写个update(),略2.dataGridView编辑列时选“DataGridViewTextBoxColumn”3.获取行 SelectRows[0] 获取列4.按钮点击事件调用update()

浪卡子县17328455029: C#中,怎么调用存储过程来插入一条记录 -
蓟宝开胸: 用存储过程插入记录和用insert 语句一样 给你个例子.CREATE PROCEDURE UP_PARTY_WRITEDOC @id int, @usercode varchar(60), --管理员可以指定gcode,也就是可以替某组发信息 @gcode varchar(60), @subject varchar(255), @...

浪卡子县17328455029: 求助,c#怎么读取SQL数据然后显示出来 -
蓟宝开胸: c#怎么读取SQL数据然后显示出来 string sql=“"//数据库查询语句 connection con=new connection(connstring); Command cmd=new Command(sql,con); con.open(); SqlDataReader dr=cmd.ExcuteReader; if(dr.read()) { this.txtid.text=dr[0];//txtid是textbox的id } dr.close(); con.close();

浪卡子县17328455029: C#调用数据库 -
蓟宝开胸: 先用C# 与数据库建立链接.用DataSet把数据接收到.TextBox.Test = DataSet.Tabel[0].Rows[0][0].ToString; 这样就接收到了.

浪卡子县17328455029: C# 求助~~~谢谢 -
蓟宝开胸: 第一个执行:<第二个执行:>第三个执行:==第四个执行:||第五个执行:&...

浪卡子县17328455029: 本人想学C#,之前有VB基础,现在在学C#时对C#的委托和多线程不怎么明白,100分求助: -
蓟宝开胸: 1、委托,你就把它当作是一种类型,它可以绑定任意个与自己(即委托本身)参数签名相同的方法,从而通过调用这个委托来间接调用该委托所绑定的方法.2、多线程,所有线程都是从运行一个函数(方法)开始,如主线程运行是从一个Main函数开始;要运行一个新的线程就要给这个线程一个方法,这样这个线程才能运行起来,而这个线程的方法是通过委托以参数的形式给的;3、总结:委托可以用作函数的参数,并且委托可以绑定任意个方法,通过调用这个委托从而间接调用该委托所帮定的所有方法;线程,要运行一个线程就要给这个线程一个方法去运行,而这个方法是通委托的形式给的.

浪卡子县17328455029: 【求助】如何编写c#代码操作数据库的表数据输出到word或excel表中???? -
蓟宝开胸: 在GridViewExportUtil.cs中,函数PrepareControlForExport是这样的:Replace any of the...

本站内容来自于网友发表,不代表本站立场,仅表示其个人看法,不对其真实性、正确性、有效性作任何的担保
相关事宜请发邮件给我们
© 星空见康网