ASP.NET Core - 日志记录系统(二)
ASP.NET Core - 日志记录系统(二)
- 2.4 日志提供程序
- 2.4.1 内置日志提供程序
- 2.4.2 源码解析
本篇接着上一篇 ASP.NET Core - 日志记录系统(一) 往下讲,所以目录不是从 1 开始的。
2.4 日志提供程序
2.4.1 内置日志提供程序
ASP.NET Core 包括以下日志记录提供程序作为共享框架的一部分:
- Console
- Debug
- EventSource
- EventLog
除此之外,还有一些微软官方提供的,但是没有和 .NET Core 框架集成的提供程序,如 ApplicationInsights 、AzureAppServicesFile 和 AzureAppServicesBlob ,这些在日常开发中使用的比较少,大家有兴趣的话可以自行了解一下。
-
控制台
Console 提供程序将输出记录到控制台。
通用主机启动时就包含了控制台日志提供程序,使用它之后,我们记录的日志在调试过程中,可以在 VS 的 “调试输出” 窗口和 “ASP.NET Core Web 服务器” 窗口(非 IIS Press 启动) 看到。使用 dotnet run 运行应用时,可以在控制台窗口中看到。以 “Microsoft” 类别开头的日志来自 ASP.NET Core 框架代码。 ASP.NET Core 和应用程序代码使用相同的日志记录 API 和提供程序。
控制台提供程序提供了多个 API,允许根据需要对输出格式、文字颜色等进行调整。
-
调试
Debug 提供程序使用 System.Diagnostics.Debug 类写入日志输出。 对 System.Diagnostics.Debug.WriteLine 的调用写入到 Debug 提供程序。
在 Linux 上,Debug 提供程序日志位置取决于分发,并且可以是以下位置之一:
- /var/log/message
- /var/log/syslog
-
事件来源
EventSource 提供程序写入名称为 Microsoft-Extensions-Logging 的跨平台事件源。 在 Windows 上,提供程序使用的是 ETW。
EventSource 日志提供程序记录的日志可以使用跨平台的 dotnet 追踪工具 dotnet-trace 来收集和跟踪。dotnet-trace 的安装和使用请参阅 dotnet-trace 诊断工具 - .NET CLI | Microsoft Learn 。
-
事件日志
仅在 Windows 系统下生效,可通过“事件查看器”进行日志查看。
EventLog 提供程序将日志输出发送到 Windows 事件日志。 与其他提供程序不同,EventLog 提供程序不继承默认的非提供程序设置。 如果未指定 EventLog 日志设置,则它们默认为 LogLevel.Warning。若要记录低于 LogLevel.Warning 的事件,请显式设置日志级别。
默认情况下,记录下来的事件日志一些基本参数如下:
- LogName:“Application”
- SourceName:“.NET Runtime”
- MachineName:使用本地计算机名称。
我们可以通过
AddEventLog
重载可以传入EventLogSettings
来修改:var builder = WebApplication.CreateBuilder(); builder.Logging.AddEventLog(eventLogSettings => {eventLogSettings.SourceName = "MyLogs"; });
上面已经讲到,在通过通用主机启动一个 .NET Core 应用时,会默认添加了 Console、Debug、EventSource 日志提供程序,如果运行平台是 Windows,还会添加 EventLog 日志提供程序。通过 ILoggingBuilder
我们可以重置并自定义日志提供程序的类型,这使得我们可以根据需要使用任何符合标准的日志提供程序。
如果是没有使用通用主机的非托管控制台应用,可以通过以下方式添加控制台日志提供程序:
using var loggerFactory = LoggerFactory.Create(builder =>
{builder.AddConsole();
});
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogInformation("Example log message");
不止控制台日志提供程序,其他各种日志提供程序都是按照日志记录系统框架进行开发和集成。显然,仅这些内置日志提供程序并不能满足我们生产开发中的使用,例如缺少最基础且常用的文件日志提供程序,还有在分布式应用已经非常普遍的业界现状下,时常需要将日志写分布式日志系统中进行统一的管理和分析,这些是微软没有提供的,但是第三方都有成熟的按照 .NET Core 日志记录系统体系架构开发的实现,这些将在下面细讲。
2.4.2 源码解析
.NET Core 日志记录系统的使用非常简单方便,其扩展性非常强,上面的章节已经讲解了基本的配置和使用,最核心的实现在于 LogeerFactory
和 ILogger
, LogeerFactory
用于日志系统的配置,ILogger
用于日志记录。下面从框架源码的角度,解析一下日志记录系统的实现。
阅读一个框架源码,我们可以从其开放出来的 API 作为入口,这样能较容易地梳理出其设计思路和实现脉络。首先是日志配置这一块,我们在应用集成的时候,对日志系统的配置都是基于 ILoggingBuilder
的,当然通过上面章节的内容,大家都已经知道在我们通过 ILoggingBuilder
进行配置之前,通用主机已经进行了一些配置。
ILoggingBuilder
的实现类其实就只是保存了容器,其他各种可用的方法都是扩展方法,都是往容器之中添加配置。
在添加日志系统默认配置的时候,可以看到显示调用了 AddLogging() 方法,之后就是像我们自己在实际应用中对日志系统进行配置一样帮我们添加了一些默认配置。
AddLogging()
方法是扩展方法,在 LoggingServiceCollectionExtensions
类中,在这个方法中往容器注入了三个日志记录系统最关键的东西,分别是 LoggerFactory
、Logger<>
和日志配置。
当我们从使用日志记录器的时候,要么就是从容器中解析,要么就是通过 LoggerFactory.CreateLogger()
方法创建,查看 Logger<>
类的实现,其内部其实也是通过 LoggerFactory
创建了 ILogger
实例,注意这里的 ILogger
是没有泛型的,最终我们使用的其实都是这一个没有泛型的。
LoggerFactory
在其初始化的时候,会从容器中解析出我们添加的日志记录提供程序以及和日记记录系统相关的配置信息,并将日志记录提供程序保存到集合中。
当调用 CreateLogger
方法时,会创建 Logger
实例,为其配置并应用过滤规则,并将其保存起来。
这里就引出了三个重要的内部实现 Logger
、LoggerInformation
和 MessageLogger
。Logger
是上面讲到的我们最终实际使用的 ILogger
的实现类,它的构造函数中需要传入 LoggerInformation
数组,LoggerInformation
数组与日志提供程序的数量对应。LoggerInformation
是一个结构体,是针对特定日志记录提供程序和日志类别的封装,在内部创建了特定于具体日志提供程序的日志记录器。
MessageLogger
是最终的日志信息书写的地方,它也是一个结构体,包含了规则过滤等内容,可以看到它的构造函数中传入了 LoggerInformation
的 Logger
属性,也就是说最终也是使用特定于日志提供程序的日志记录器的。
最终返回的 MessageLogger
数组赋值给了 Logger
,MessageLogger
数组不一定与日志记录提供程序的数量一样,因为有些日志记录提供程序在规则配置检查中可能跳过了。
Logger
类应用了装饰器模式,对多种日志记录提供程序的记录器进行了包装,提供了统一的日志记录 API,使得我们在使用时可以通过统一的入口将日志同时书写到不同的地方。当我们调用 Logger
实例的 Log
方法时,实际上是遍历了 MessageLogger
数组,通过具体的日志提供程序对应的日志记录器对当前日志级别进行检查,并进行最终的日志记录。
以控制台提供程序为例,这里中间有很多代码,其实只是为了实现更好的扩展性和性能,可以先忽略不看,最终也只是返回了特定 ConsoleLogger
。
而 ConsoleLogger
中的 Log
方法最终是将日志信息放到队列中,再由队列处理器写到控制台中。
了解完 .NET Core 日志记录系统的整体实现逻辑之后,我们想实现一个自己的日志提供程序其实还是比较简单的,当然如果要像微软内置的日志记录提供程序,或者第三方成熟的日志框架那样,各种细节处理得很好,就稍微有些难度了。以下是一个简单的示例,模仿默认日志记录提供程序的的实现方式,将日志记录到文件中:
(1) 创建一个类库项目,并引入以下依赖包
Install-Package Microsoft.Extensions.Logging.Abstractions
Install-Package Microsoft.Extensions.Logging
(2) 首先是实现 ILogger
接口,提供我们的日志记录器
internal sealed class WeWantFileLogger : ILogger
{private readonly object _sync = new object();/// <summary>/// 创建日志记录域/// </summary>/// <typeparam name="TState"></typeparam>/// <param name="state"></param>/// <returns></returns>/// <exception cref="NotImplementedException"></exception>public IDisposable? BeginScope<TState>(TState state) where TState : notnull{// 由于不准备支持日志记录域功能,这里返回一个空实现return NullScope.Instance;}/// <summary>/// 判断是否记录日志/// </summary>/// <param name="logLevel"></param>/// <returns></returns>public bool IsEnabled(LogLevel logLevel){return logLevel != LogLevel.None;}/// <summary>/// 记录日志,这里简单的演示例子/// 一个可用于正式环境的文件记录器还需考虑很多可扩展性、性能等因素/// </summary>/// <typeparam name="TState"></typeparam>/// <param name="logLevel"></param>/// <param name="eventId"></param>/// <param name="state"></param>/// <param name="exception"></param>/// <param name="formatter"></param>public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func<TState, Exception?, string> formatter){if (!IsEnabled(logLevel)){return;}ThrowHelper.ThrowIfNull(formatter);string message = formatter(state, exception);if(string.IsNullOrEmpty(message)){return;}message = $"{logLevel}: {message} { Environment.NewLine }";if(exception != null){message += Environment.NewLine + Environment.NewLine + exception;}var filePath = Path.Combine(Directory.GetCurrentDirectory(), "log.txt");lock (_sync){System.IO.File.AppendAllText(filePath, message);}}
}
其他相关的类如下:
internal sealed class NullScope : IDisposable
{public static NullScope Instance = new NullScope();private NullScope() { }public void Dispose(){}
}internal static partial class ThrowHelper
{/// <summary>Throws an <see cref="ArgumentNullException"/> if <paramref name="argument"/> is null.</summary>/// <param name="argument">The reference type argument to validate as non-null.</param>/// <param name="paramName">The name of the parameter with which <paramref name="argument"/> corresponds.</param>internal static void ThrowIfNull(
#if NETCOREAPP3_0_OR_GREATER[NotNull]
#endifobject? argument,[CallerArgumentExpression("argument")] string? paramName = null){if (argument is null){Throw(paramName);}}#if NETCOREAPP3_0_OR_GREATER[DoesNotReturn]
#endifprivate static void Throw(string? paramName) => throw new ArgumentNullException(paramName);
}[AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
internal sealed class CallerArgumentExpressionAttribute : Attribute
{public CallerArgumentExpressionAttribute(string parameterName){ParameterName = parameterName;}public string ParameterName { get; }
}
(3) 然后是实现 ILoggerProvider
接口,提供日志记录提供程序
[ProviderAlias("WeWantFile")]
public class WeWantFileLoggerProvider : ILoggerProvider
{public ILogger CreateLogger(string categoryName){return new WeWantFileLogger();}public void Dispose(){}
}
(4) 提供相应的扩展方法
public static class WeWantFileLoggerFactoryExtensions
{public static ILoggingBuilder AddWeWantFile(this ILoggingBuilder builder){builder.Services.TryAddEnumerable(ServiceDescriptor.Singleton<ILoggerProvider, WeWantFileLoggerProvider>());return builder;}
}
(5) 在之前的项目中引用,并进行以下配置
// 清除默认的日志记录提供程序,添加自定义的日志记录提供程序
builder.Logging.ClearProviders();
builder.Logging.AddWeWantFile();
(6) 测试日志记录
调用之前测试用的 Web API 接口,代码如下:
// 各种日志API对应各种日志级别
// 断点
_logger.LogTrace("这是一个断点日志");
//调试
_logger.LogDebug("this is a debug.");
//信息
_logger.LogInformation("this is an info.");
//警告
_logger.LogWarning("this is a warning.");
//错误
_logger.LogError("this is an error.");
//当机
_logger.LogCritical("this is Critical");
可以看到项目文件夹中多了 log.txt文件,内容如下:
.NET Core 下的日志记录系统大概就介绍到这里,后面再继续介绍一下一些第三方日志框架,怎么将其集成到 .NET Core 框架中进行正式生产环境下的应用。
参考文章:
.NET Core 和 ASP.NET Core 中的日志记录 | Microsoft Learn
理解ASP.NET Core - 日志(Logging) - xiaoxiaotank - 博客园 (cnblogs.com)
相关文章:
ASP.NET Core - 日志记录系统(二)
ASP.NET Core - 日志记录系统(二) 2.4 日志提供程序2.4.1 内置日志提供程序2.4.2 源码解析 本篇接着上一篇 ASP.NET Core - 日志记录系统(一) 往下讲,所以目录不是从 1 开始的。 2.4 日志提供程序 2.4.1 内置日志提供程序 ASP.NET Core 包括…...
阿里云直播互动Web
官方文档:互动消息Web端集成方法_视频直播(LIVE)-阿里云帮助中心 以下是代码实现: <!-- 引入阿里云互动文件 --> <script src"https://g.alicdn.com/code/lib/jquery/3.7.1/jquery.min.js"></script> <script src&quo…...
解锁无证身份核验:开启便捷安全新征程
在当今快速发展的数字化时代,身份核验作为确保信息安全与交易诚信的基石,正经历着前所未有的变革。传统的身份核验方式,如携带身份证件进行现场验证,虽在一定程度上保障了安全,却也带来了诸多不便。随着科技的进步&…...
[DO374] Ansible 配置文件
[DO374] Ansible 配置文件 1. 配置文件位置2. 配置文件3. Ansible 配置4. Ansible的Ad-hoc5. Ansible 模块6. playbook段落7. 任务执行后续8. Ansible 变量8.1 ansible 变量的定义8.1.1 主机变量8.1.2 主机组变量 8.2 vars的循环 9. Ansible Collection10. Ansible-galaxy 安装…...
【杂谈】-50+个生成式人工智能面试问题(四)
7、生成式AI面试问题与微调相关 Q23. LLMs中的微调是什么? 答案:虽然预训练语言模型非常强大,但它们并不是任何特定任务的专家。它们可能对语言有惊人的理解能力,但仍需要一些LLMs微调过程,开发者通过这个过程提升它…...
RuoYi Cloud项目解读【四、项目配置与启动】
四、项目配置与启动 当上面环境全部准备好之后,接下来就是项目配置。需要将项目相关配置修改成当前相关环境。 1 后端配置 1.1 数据库 创建数据库ry-cloud并导入数据脚本ry_2024xxxx.sql(必须),quartz.sql(可选&…...
51c~Pytorch~合集5
我自己的原文哦~ https://blog.51cto.com/whaosoft/13059544 一、PyTorch DDP 正在郁闷呢 jetson nx 的torchvision安装~~ 自带就剩5g 想弄到ssd 项目中的 venv中又 cuda.h没有... 明明已经装好什么都对 算了说今天主题 啊对 还是搬运啊 学习之工具人而已 勿怪 Distrib…...
【芯片封测学习专栏 -- 什么是 Chiplet 技术】
请阅读【嵌入式开发学习必备专栏 Cache | MMU | AMBA BUS | CoreSight | Trace32 | CoreLink | ARM GCC | CSH】 文章目录 OverviewChiplet 背景UCIeChiplet 的挑战 Overview Chiplet 又称为小芯片。该技术通过将大型SoC划分为更小的芯片,使得每个部分都能采用不同…...
Java SpringBoot + Vue + Uniapp 集成JustAuth 最快实现多端三方登录!(QQ登录、微信登录、支付宝登录……)
注:本文基于 若依 集成just-auth实现第三方授权登录 修改完善,所有步骤仅代表本人如下环境亲测可用,其他环境需自辩或联系查看原因! 系统环境 运行系统:Windows10专业版、Linux Centos7.6 Java 版本:1.8.0_…...
支持向量回归(SVR:Support Vector Regression)用于A股数据分析、预测
简单说明 支持向量回归是一种用来做预测的数学方法,属于「机器学习」的一种。 它的目标是找到一条「最合适的线」,能够大致描述数据点的趋势,并允许数据点离这条线有一定的误差(不要求所有点都完全落在这条线上)。 可以把它想象成:找到一条「宽带」或「隧道」,大部分…...
ZYNQ初识10(zynq_7010)UART通信实验
基于bi站正点原子讲解视频: 系统框图(基于串口的数据回环)如下: 以下,是串口接收端的波形图,系统时钟和波特率时钟不同,为异步时钟,,需要先延时两拍,将时钟同…...
专题 - STM32
基础 基础知识 STM所有产品线(列举型号): STM产品的3内核架构(列举ARM芯片架构): STM32的3开发方式: STM32的5开发工具和套件: 若要在电脑上直接硬件级调试STM32设备,则…...
2 XDMA IP中断
三种中断 1. Legacy 定义:Legacy 中断是传统的中断处理方式,使用物理中断线(例如 IRQ)来传递中断信号。缺点: 中断线数量有限,通常为 16 条,限制了可连接设备的数量。中断处理可能会导致中断风…...
自然语言转 SQL:通过 One API 将 llama3 模型部署在 Bytebase SQL 编辑器
使用 Open AI 兼容的 API,可以在 Bytebase SQL 编辑器中使用自然语言查询数据库。 出于数据安全的考虑,私有部署大语言模型是一个较好的选择 – 本文选择功能强大的开源模型 llama3。 由于 OpenAI 默认阻止出站流量,为了简化网络配置&#…...
抖音矩阵是什么
抖音矩阵是指在同一品牌或个人IP下,通过创建多个不同定位的抖音账号(如主号、副号、子号等),形成一个有机的整体,以实现多维度、多层次的内容覆盖和用户互动。以下是关于抖音矩阵的详细介绍: 抖音矩阵的类…...
怎么抓取ios 移动app的https请求?
怎么抓取IOS应用程序里面的https? 这个涉及到2个问题 1.电脑怎么抓到IOS手机流量? 2.HTTPS怎么解密? 部分app可以使用代理抓包的方式,但是正式点的app用代理抓包是抓不到的,例如pin检测,证书双向校验等…...
pyqt鸟瞰
QApplication是Qt框架中的一个类,专门用于管理基于QWidget的图形用户界面(GUI)应用程序的控制流和主要设置。QApplication类继承自QGuiApplication,提供了许多与GUI相关的功能,如窗口系统集成、事件处理等。 QAppli…...
【Docker】入门教程
目录 一、Docker的安装 二、Docker的命令 Docker命令实验 1.下载镜像 2.启动容器 3.修改页面 4.保存镜像 5.分享社区 三、Docker存储 1.目录挂载 2.卷映射 四、Docker网络 1.容器间相互访问 2.Redis主从同步集群 3.启动MySQL 五、Docker Compose 1.命令式安装 …...
Token和JWT的关系详细讲解
Token 和 JSON Web Token (JWT) 是两个相关但概念上不同的术语,它们在现代 Web 应用程序的身份验证和授权中扮演着重要角色。下面将详细介绍两者之间的关系以及 JWT 的具体工作原理。 1. Token 概述 Token 是一种广义的概念,指的是任何可以证明用户身份…...
【Linux系列】Curl 参数详解与实践应用
💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...
解决 Git SSL 连接错误:OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno
问题描述 在执行 git pull 命令时遇到以下错误: > git pull --tags origin main fatal: unable to access github仓库: OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 0这个错误通常表示 Git 在尝试通过 HTTPS 连接到 GitHub 时遇到了 SSL 连接问题。 解决方案…...
《Vue3 八》<script setup> 语法
<script setup> 是在单文件中使用 Composition API 的编译时语法糖,里面的代码会被编译成组件 setup() 函数的内容。 <script setup> 中的代码在每次组件实例被创建的时候都都会被执行。 定义数据: 在 <script setup> 语法糖的写法中…...
51单片机和STM32集成蓝牙模块实用指南
51单片机和STM32集成蓝牙模块实用指南 蓝牙模块(如HC-05、HC-06、JDY-31等)是嵌入式开发中常用的无线通信模块,广泛应用于智能家居、物联网、机器人等领域。本文将详细介绍如何将蓝牙模块集成到 51单片机 和 STM32 中,并提供一个…...
Transformer:深度学习的变革力量
深度学习领域的发展日新月异,在自然语言处理(NLP)、计算机视觉等领域取得了巨大突破。然而,早期的循环神经网络(RNN)在处理长序列时面临着梯度消失、并行计算能力不足等瓶颈。而 Transformer 的横空出世&am…...
sql 函数
# 四则运算 - * / # 函数 distinct 、count、sum、max、min、avg、sum、round select concat(device_id 是,device_id ) device_id from device_id_apply_factor where device_id D6A42CE6A0; select concat_ws(|||,device_id ,factor_a ,module_type) from 、device_id_app…...
C# OpenCV机器视觉:OCR产品序列号识别
在一个看似平常却又暗藏玄机的工作日,阿明正坐在办公室里,对着堆积如山的文件唉声叹气。突然,电话铃声如炸雷般响起,吓得他差点从椅子上摔下来。原来是公司老板打来的紧急电话:“阿明啊,咱们刚生产出来的那…...
2012wtl,学习活扩
原文 WTL学习注意–活扩 在Win32下,活扩控件已是个成熟的概念了,即使对COM不太了解,使用活扩控件仍是件容易的事情.既然是控件,无非要关注两个方面,第一是如何调用它的函数,其次是如何接收它的事件. 看看在WTL中,如何使用活扩控件(基本对话框): 1.创建项目时,让对话框支持活…...
使用Deepseek搭建类Cursor编辑器
使用Deepseek搭建类Cursor编辑器 Cursor想必大家都用过了,一个非常强大的AI编辑器,在代码编写上为我们省了不少事,但高昂的价格让我们望而却步,这篇文章教你在Visual Studio Code上搭建一个类Cursor的代码编辑器。 步骤其实非常…...
mysql,PostgreSQL,Oracle数据库sql的细微差异(2) [whith as; group by; 日期引用]
sql示例(MySQL) WITHtemp1 AS (SELECT name AS resultsFROM Users uJOIN MovieRating m ON u.user_id m.user_idGROUP BY m.user_idORDER BY COUNT(*) DESC,left(name,1)LIMIT 1),temp2 AS (SELECT title AS resultsFROM Movies mJOIN MovieRating r ON m.movie_id r.movie_…...
基于改进粒子群优化的无人机最优能耗路径规划
目录 1. Introduction2. Preliminaries2.1. Particle Swarm Optimization Algorithm2.2. Deep Deterministic Policy Gradient2.3. Calculation of the Total Output Power of the Quadcopter Battery 3.OptimalEnergyConsumptionPathPlanningBasedonPSO-DDPG3.1.ProblemModell…...
莱阳做网站/网络营销学什么内容
简直智障,上一题V题,样例输出里面的“Case:”不要输出,到了这题又是要输出的了 #include<iostream> using namespace std; int num[100000]; int main() {int T;for(int i32;i<100;i){num[i*i]1;}cin>>T;int n;int…...
买了域名之后怎么建设网站/百度关键词搜索排名查询
导读: 本文将对 Linux™ 程序员可以使用的内存管理技术进行概述,虽然关注的重点是 C 语言,但同样也适用于其他语言。文中将为您提供如何管理内存的细节,然后将进一步展示如何手工管理内存,如何使用引用计数或者内存池来…...
番禺企业网站建设/新平台怎么推广
Laravel 8 附带了很酷的新特性,并对队列系统的一些更改。在本文中,我们将研究这些特性和更改。变化Backoff (回退)已将 retryAfter() 方法和 retryAfter 排队作业,邮件,通知和侦听器的属性重命名为 backoff。php artisan queue&am…...
中国联通网站备案系统/接广告的平台推荐
题目 小明 PAT 考了满分,高兴之余决定发起微博转发抽奖活动,从转发的网友中按顺序每隔 N 个人就发出一个红包。请你编写程序帮助他确定中奖名单。 输入格式: 输入第一行给出三个正整数 M(≤ 1000)、N 和 Sÿ…...
商丘做手机做网站/好项目推荐平台
GTK中的构件II(Widgets)GTK中的构件II(Widgets)在本章的GTK程序设计中,我们仍然要继续向大家介绍和展示各种各样的构件。GtkComboBoxGtkComboBox构件的作用是让程序使用者根据不同的需求从很多选项中进行选择。#include <gtk/gtk.h>void combo_selected(GtkWi…...
国内最好的网站建设/网站开发与设计
默认用户有这么几个,system,sys,scott,hr ,一般scott 和hr 作为你的练习用户.system的默认密码是 managersys的默认密码是 change_on_install练习用户,oracle 10g 以后需要解锁.使用sys或者system 用户登录以后,使用如下命令解锁alter user scott identified by tiger account …...