• SharePoint 知识总结


     

    知识点总结

     

    目录

    获得List

    初始上传,还没有Check In过的File删除

    SPListCollectionDatatable

    Folder类型添加自定义属性

    多行文本取出换行

    识别为垃圾邮件

    使用MOSS自带的方法发送email

    .net方式发送email

    更新审批状态

    stringGuid

    Content Type

    显示个人信息

    长时间操作,不超时

    转向

    内容类型

    AD操作

    List附件的读取

    模拟用户代码

    People Editor控件

    工作流历史记录表

    AJAX实现

    Person or Group字段允许多人时,通过sdk对象读取用户信息

    代码启动工作流

    CAML查找Lookup

    WEB页面显示word

    多文件上传

    工作流中权限

    检查权限

    添加权限

    无法查询文件夹下的item,只能查找根目录的解决办法:

    如何从SPAttachmentCollection中获取到SPfile

    如何查看SharePoint未知错误

    Webpart出错,无法打开页面,contents=1 ,会转到webpart管理页面,把出问题的删掉

    URL后面加入“?&toolpaneview=2”打开设计页

    或者加“DisplayMode=Design”

    http://Site/_layouts/spcontnt.aspx?&url=/_catalogs/wp/forms/editForm.aspx这页面是维护页面

    “超链接或图片”类型栏的值,对应的对象模型为SPFieldUrlSPFieldUrlValue,可以这样读取:

    将子网站移动到主网站???

    如何定义一个Group

    将一个Group分配进一个Role

    读取User Profile

    关闭EventHandler

    SharePoint中访问AD

    System.DictionaryService

    SPMenu 导航栏

    获得List

             List如果Title经常变化,可以使用SPWeb对象的GetList方法来获取SPList对象,该方法可以通过列表的Url获取到列表的对象。或者直接使用GUID,但是GUID不适用于系统迁移,如QASPRD

    初始上传,还没有Check In过的File删除

             if(spFile.CheckOutStatus != SPFile.SPCheckOutStatus.None)

    {

     spFile.CheckIn(string.Empty);

    }

    SPListCollectionDatatable

          SPListItemCollection unprocessedItems = List.GetItems(query);

    DataTable dt1 = unprocessedItems.GetDataTable();

    Folder类型添加自定义属性

        mySite = new SPSite("http://richsql/");

                    myWeb = mySite.RootWeb;

                    SPDocumentLibrary spDoc = myWeb.Lists["JackDocuments"] as SPDocumentLibrary;

                    SPContentTypeCollection spcontents = spDoc.ContentTypes;

                    string strCTName = string.Empty;

                    foreach (SPContentType spContextType in spcontents)

                    {

                   if (spContextType.Name == "Folder")

                        {

                            spContextType.Sealed = false;

                            spContextType.Update();

                        }

                    }

     Sealed 属性设置成false就可以了.

     

    多行文本取出换行

          Replace(""r"n", "<br/>")

    识别为垃圾邮件

    来历不明的软件发的邮件都是垃圾邮件。

    所以发邮件的时候要套个马甲。

    这个代码就是套个OutLook作掩护。

            public bool Send(string Subject, string Body, string To, string MailFrom, string MailFromName, string MailDomain, string MailServerUserName, string MailServerPassWord)

            {

                try

                {

                    MailMessage msg = new MailMessage();

                    msg.From = new MailAddress(MailFrom, MailFromName);

                    msg.To.Add(new MailAddress(To, To));

                    msg.Subject = Subject;

                    msg.Body = Body;

                    msg.IsBodyHtml = true;

                    msg.Priority = MailPriority.Normal;

                    msg.SubjectEncoding = System.Text.Encoding.UTF8;

                    msg.BodyEncoding = System.Text.Encoding.UTF8;

                     //以下附加头用于避免被识别为垃圾邮件

                    msg.Headers.Add("X-Priority", "3");

                    msg.Headers.Add("X-MSMail-Priority", "Normal");

                    msg.Headers.Add("X-Mailer", "Microsoft Outlook Express 6.00.2900.2869");

                    msg.Headers.Add("X-MimeOLE", "Produced By Microsoft MimeOLE V6.00.2900.2869");

                    msg.Headers.Add("ReturnReceipt", "1");

                     //附加结束

                    SmtpClient client = new SmtpClient(MailDomain);

                    client.UseDefaultCredentials = false;

                    client.Credentials = new NetworkCredential(MailServerUserName, MailServerPassWord); //帐号密码

                    client.DeliveryMethod = SmtpDeliveryMethod.Network;

                    client.Send(msg);

                   return true;

                }

                catch { return false; }

            }

    使用MOSS自带的方法发送email    

                    StringDictionary messageHeaders = new StringDictionary();

                    messageHeaders.Add("to", email);

                    messageHeaders.Add("subject", s_subject);

                    //messageHeaders.Add("from", "");

                    messageHeaders.Add("content-type", "text/html");

                    //messageHeaders.Add("cc", "");

                    //messageHeaders.Add("bcc", "");

                    SPUtility.SendEmail(this.Web, messageHeaders, s_body);

    .net方式发送email

            public static bool SendMail(string to,string subject,string body)

            {

                MailAddress from = new MailAddress("MOSS-Test1@XXX.com");

                MailAddress toUser = new MailAddress(to);

                MailMessage mailobj = new MailMessage(from, toUser);

                //完善MailMessage对象

                mailobj.Subject = subject;

                mailobj.Body = body;

                mailobj.IsBodyHtml = true;

                mailobj.BodyEncoding = System.Text.Encoding.GetEncoding("UTF-8");

                mailobj.Priority = MailPriority.Normal;

                //构建SmtpClient对象

                SmtpClient smtp = new SmtpClient("mail.xxx.com");

                try

                {

     

                    smtp.Send(mailobj);

                    return true;

                }

                catch

                {

                    return false;

                }

            }

         我们使用.NET类库中的APIMail的时候,我们要配置他的SMTP Server等,但是在Sharepoint里,已经提供了相关的封装的方法:

    SPUtility.SendEmail(SPWeb, false, false,"to@mail.com", "MailTitle","MailBody");

    上面的方法只能以To的形式来发Mail,有的时候我们需要使用CC BCC,我们可以利用该函数的另一个重载来实现:

    SPUtility.SendEmail(web, messageHeaders, messageBody, appendFooter)

    我们需要设置messageHeaders,代码如下:

    StringDictionary headers = new StringDictionary();

    headers.Add("To","To@Mail.com");

    headers.Add("CC","CC@Mail.com");

    headers.Add("Bcc","BBC@Mail.com");

    headers.Add("From","From@Mail.com");

    headers.Add("subject","The Mail Title");

    headers.Add("content-type","text/html");

    header中可以指定To CC BCC From等,当然使用上面的函数的前提是你在管理中心已经配置好了传出电子邮件的设置。

    更新工作流状态

         SPList list = web.List["TestList"];

    SPListItem listItem = list.GetItemById(1);

    string state = listItem.Fields["审批状态"].InternalName;

    listItem[state] = 0;    //设置列表审批状态为“已批准”(0表示 已批准)

    listItem.SystemUpdate();    //列表使用SystemUpDate()方法来更新审批状态。

    更新审批状态

    SPDocumentLibrary docLib = web.List["TestLib"];

    SPListItem libItem = list.GetItemById(1);

    string state = libItem.Fields["审批状态"].InternalName;

    libItem[state] = 0;    //设置文档库审批状态为“已批准”(0表示已批准)

    libItem.UpdateOverwriteVersion();    //文档库使用UpdateOverwriteVersion()方法来更新审批状态。

     

    item["_ModerationStatus"] = (int)SPModerationStatusType.Approved;

    item.Update();

    这样好像就可以

    stringGuid

         Guid dd = new guidstr);

    Content Type

           Item[ContentTypeId]或者Item[ContentType]

    显示个人信息

    SPD打开根站点

    在根下 _catalogs 目录有 users(用户信息表)

    此表是网站集所管理的用户列表。默认为隐藏。

    点右键 属性--设置-- 钩掉“在浏览器中隐藏”选项。

    此时,用户表 就可以像其他列表一样操作

    要实现 显示照片和姓名 职务 部门等信息

    可以通过webpart 显示指定列信息,转换为XSLT视图,进行定制

    注意设置筛选条件 为:   ID  = [当前用户]

    最终可以自由定制。

    Item.SystemUpdate();

    方法

    更改时间

    更改者

    事件

    更改和审核记录

    订阅

    properties are not demoted into documents

    增加版本

    SystemUpdate()

    ×

    ×

    ×

    ×

    ×

    SystemUpdate

    (Bool)

    ×

    ×

    ×

    ×

    False不增加

    长时间操作,不超时

    SPLongOperation oparetion = new SPLongOperation(this);

            try

            {

                oparetion.Begin();

                try

                {

                    //启动工作流

                    //StartInitData参数为ApproveWFAssociationData类的序列化后的string

                    web.Site.WorkflowManager.StartWorkflow(listItem, workflowAssociation, StartInitData());

                }

                catch (Exception ex)

                {

                    throw new Exception(ex.ToString());

                }

                oparetion.End(list.DefaultViewUrl);

            }

            finally

            {

                if (oparetion != null)

                {

                    oparetion.Dispose();

                }

            }

    转向

              // 转向到该list的工作流设置页面

                SPUtility.Redirect("WrkSetng.aspx?List=" + taskList.ID,

                                                            SPRedirectFlags.RelativeToLayoutsPage, HttpContext.Current);

    转到错误页

                            SPUtility.TransferToErrorPage("The CreateChildControls function of the AjaxBasePart has not been called. You probably need to add ""base.CreateChildControls()"" to the top of your CreateChildControls override.");

           成员名称    说明

           CheckUrl   Check the redirect Uniform Resource Locator (URL). 

           Default     Use default settings for the redirect. 

           DoNotEncodeUrl Do not encode the redirect URL. 

           DoNotEndResponse    Do not end the response after the redirect. 

           RelativeToLayoutsPage      相对Layouts的地址The redirect occurs relative to the layouts page. 

           RelativeToLocalizedLayoutsPage 相对触发的layoutsPage的地址The redirect occurs relative to the localized layouts page. 

           Static       静态地址,非相对地址The redirect is static. 

           Trusted     The redirect is trusted. 

           UseSource 使用URL中的Source的地址Use the source for the redirect. 

    http://msdn.microsoft.com/zh-cn/library/microsoft.sharepoint.utilities.spredirectflags.aspx

    内容类型

    SPWeb.AvailableContentTypes得到当前web所有活动的内容类型

    SPWeb.ContentTypes 得到部署到当前web上的内容类型,不要用这个。

    Web的用户list

    web.SiteUserInfoList

    AD操作

    DirectoryEntry di = new DirectoryEntry("LDAP://ADServer/OU=开发部,administrator,pass, AuthenticationTypes.Secure);

    广州㊣-jian(:

    这句应该是最关键的了

    广州㊣-jian(:

    然后想在“开发部”下面增加用户,就用di.Children.Add就可以了

    List附件的读取

    怎么取得sharepoint表单库中的表单附件的数据,我想将附件数据单独的提取出来,但是提取的信息全是BASE64编码,有没有这方面的信息或资料,

    BASE64 解码不就完了

    System.Convert.FromBase64String

    模拟用户代码

    string siteUrl = "http://bbs.msiw.net:82/sites/sjs" ;

                //首先用管理员身份取到某个用户的Token,必须,非管理员无法模拟

                SPSite site = new SPSite(siteUrl);

                //此时用户为SHAREPOINT"system

                Response.Write(site.RootWeb.CurrentUser);

                SPUser user = site.RootWeb.SiteUsers["saicmotorlab""user1"];

                //利用用户Token构造新的Site对象

                SPSite siteWithUser = new SPSite(siteUrl, user.UserToken);

                SPWeb webWithUser = siteWithUser.RootWeb;

                //此时用户为SAICMOTORLAB"user1

                Response.Write( webWithUser.CurrentUser );

                SPList listWithUser = webWithUser.Lists["simeList"];

                //dother code

    People Editor控件

              PeopleEditor.SelectionSet = "User,DL,SecGroup";

        代表可以选择用户,也可以选择组

    工作流历史记录表

        http://cnsh-10apl1/ProjectManagement/Lists/Workflow History/

    Infopath中为下拉框添加值

    testNode.AppendChildElement(testNode.Prefix, "AddElm",testNode.NamespaceURI, string.Empty);

     

    AJAX实现

          3:在相关MasterPage<head>里添加

    <script type='text/javascript'>_spOriginalFormAction = document.forms[0].action;

    _spSuppressFormOnSubmitWrapper=true;</script>

    4.在你写好的UserControlPage_load事件里添加

    if (this.Page.Form != null)

                 {

                     string formOnSubmitAtt = this.Page.Form.Attributes["onsubmit"];

                     if (formOnSubmitAtt == "return _spFormOnSubmitWrapper();")

                     {

                         this.Page.Form.Attributes["onsubmit"] =

    "_spFormOnSubmitWrapper();";

                     }

                 }

                 ScriptManager.RegisterStartupScript(this,

    typeof([UserControlClassName]), "UpdatePanelFixup", "_spOriginalFormAction =

    document.forms[0].action; _spSuppressFormOnSubmitWrapper=true;", true);

    Person or Group字段允许多人时,通过sdk对象读取用户信息

    /// <summary>

            /// ª¡§y"Item["User"]"Ì?Ì?SPUser

            /// </summary>

            /// <param name="web"></param>

            /// <param name="p">"Item["User"]"</param>

            /// <returns>"SPUser"</returns>

            ///

            public SPUser getUserByField(object p)

            {

                SPUser user2 = default(SPUser);

                if (p != null)

                {

                    SPSecurity.RunWithElevatedPrivileges(delegate()

                    {

                        using (SPSite site2 = new SPSite(SPContext.Current.Site.ID))

                        {

                            using (SPWeb web2 = site2.OpenWeb(SPContext.Current.Web.ID))

                            {

                                SPFieldUserValue userValue = new SPFieldUserValue(web2, p.ToString());

                                user2 = userValue.User;

                            }

                        }

                    });

                }

                else

                {

                    user2 = null;

                }

                return user2;

     

            }

            /// <summary>

            /// ¤¦Ì?List<SPUser>

            /// </summary>

            /// <param name="item">SPlistItem</param>

            /// <param name="fieldName">?À¨ºÁ???</param>

            /// <returns>¤¦Ì?Users</returns>

            protected List<SPUser> GetUsersFromSPFieldUser(SPListItem item, string fieldName)

            {

                List<SPUser> users = new List<SPUser>();

                SPSecurity.RunWithElevatedPrivileges(delegate()

                {

                    using (SPSite site2 = new SPSite(SPContext.Current.Site.ID))

                    {

                        using (SPWeb web2 = site2.OpenWeb(SPContext.Current.Web.ID))

                        {

                            SPFieldUser uField = item.Fields[fieldName] as SPFieldUser;

                            if (!uField.AllowMultipleValues && item[fieldName] != null//¨º¨ª¨¤???

                            {

                                SPFieldUserValue userValue = new SPFieldUserValue(web2, item[fieldName].ToString());

                                users.Add(userValue.User);

                            }

                            else

                            {

                                SPFieldUserValueCollection userValues = item[fieldName] as SPFieldUserValueCollection;

                                foreach (SPFieldUserValue userValue in userValues)

                                {

                                    if (null != userValue.User)

                                    {

                                        users.Add(userValue.User);

                                    }

                                    else

                                    {

                                        SPGroup userGroup = web2.SiteGroups.GetByID(userValue.LookupId);

                                        foreach (SPUser user in userGroup.Users)

                                        {

                                            users.Add(user);

                                        }

                                    }

                                }

                            }

                        }

                    }

                });

               

                return users;

            }

    代码启动工作流

              获取spworkflowmanager 获取spworkflowassociation,针对一个item启动

    Item中添加附件

         if (fileUploadAttach.HasFile)

                    {

                        Stream stream = fileUploadAttach.PostedFile.InputStream;

                        stream.Position = 0;

                        byte[] buffer = new byte[stream.Length];

                        stream.Read(buffer, 0, (int)stream.Length);

                        itemNew.Attachments.Add(fileUploadAttach.PostedFile.FileName, buffer);

                        itemNew.Update();

                        itemNew.ParentList.Update();

                        stream.Close();

                    }

    CAML查找Lookup

         <FieldRef Name="GMP" LookupId="TRUE"/>

             <Value Type="Lookup">1</Value>

    用户型

             "<FieldRef Name=""User"" LookupId=""TRUE""/>" +

              "<Value Type=""User"">" + user.ID + "</Value>" +

    WEB页面显示word

              如果想让web页面显示出word文档要加

    Response.ContentType = "application/msword";

    Response.AddHeader("Content-Disposition","attachment;filename=" +

    HttpUtility.UrlEncode(file.FILENAME).Replace("+","%20"));// 防止乱码

    Response.Charset="UTF-8";

    Response.ContentEncoding=System.Text.Encoding.Default;

    Response.BinaryWrite(文件流);

    Response.End();

    多文件上传

              SPFileCollection destFiles =

        siteCollection.AllWebs["Destination_Site"]

        .Folders["Destination_DocLib"].Files;

     

    foreach (SPFile srcFile in srcFolder.Files)

    {

        if (srcFile.TimeLastModified <

            Convert.ToDateTime("12/5/2002 12:00:00 AM"))

        {

            string destURL = destFiles.Folder.Url + "/" + srcFile.Name;

            byte[] binFile = srcFile.OpenBinary();

                                        destFiles.Add(destURL, binFile, true);

        }

    }

    工作流中权限

              HybridDictionary一个对象叫task1permission,然后task1permission.Add(taskProps.AssignedTo, SPRoleType.Contributor),最后将task1permission赋值给taskSpecialPermissions

    检查权限

    public void CheckPermissions (SPBasePermissions permissionMask)

    检查当前用户是否有permissionMask的权限,如果没有返回一个UnauthorizedAccessException的异常。

    Bool havePermission = SPList.DoesUserHavePermissions(SPBasePermissions permissionMask)

    添加权限

    SPList DTTasks = web2.Lists["Document Tasks"];

    SPRoleAssignment roleAssignForMember = new SPRoleAssignment((SPPrincipal)newGroup); //newGroup个组分配权限

    SPRoleDefinition roleDefForMemberr = web2.RoleDefinitions["DTMembers"];

    roleAssignForMember.RoleDefinitionBindings.Add(roleDefForMemberr);

     

    if (!DTTasks.hasUniqueRoleAssignments)//如文件夹没有独立的权限

        {

           DTTasks.BreakRoleInheritance(false);      //删除文件夹继承的权限 true删除的同时继承false删除的同时不继承

         }

    DTTasks.RoleAssignments.Add(roleAssignForMember);

    TTasks.Update();

     

    无法查询文件夹下的item,只能查找根目录的解决办法:

    query.ViewAttributes = " Scope='Recursive' "

           Member name   Description

           Default     Show only the files and subfolders of a specific folder. 

           FilesOnly   Show only the files of a specific folder. 

           Recursive Show all files of all folders. 

           RecursiveAll      Show all files and all subfolders of all folders. 

    The SPViewScope enumeration is used with the Scope property of the SPView class.

    EventHandler中的Adding Updating等操作如何赋值

    public override void ItemAdding(SPItemEventProperties properties)

    {

        // Demo1: 在新建时取用户输入的值并作修改

        string newValue = "新的值是:" + properties.AfterProperties["Title"].ToString();

        properties.AfterProperties.ChangedProperties.Add("Title", newValue);

    }

    如何从SPAttachmentCollection中获取到SPfile

    SPAttachmentCollection attachments = item.Attachments;

              if (attachments.Count > 0)

                 {

                   for (int i = 0; i < attachments.Count; i++)

                      {

                         string url = attachments.UrlPrefix + attachments[i];//得到附件的共同前缀再加上附件的名称

                         SPFile file = web.GetFile(url);

                         string customerName = item["Customer Name"].ToString().Split('#')[1];

                         file.CopyTo(properties.WebUrl + "/CRM Document/" + customerName + "/04 Customer Scoring/" + attachments[i], true);

                                }

    如何查看SharePoint未知错误

    MOSS开发自定义功能后,出现错误页面只显示“出现未知错误”的提示,查看很不方面,通过下面方法就可以直接在出错页面查看错误信息。

     

    修改Web应用程序根目录上的Web.config文件中的两个地方:

    查找以下位置并更改即可(红色为更改前后的值)

    一、MaxControls="200" CallStack="false"   改为 MaxControls="200" CallStack="true"

    二、customErrors mode="On" 改为 customErrors mode="Off"

     

    Webpart出错,无法打开页面,contents=1 ,会转到webpart管理页面,把出问题的删掉

    URL后面加入“?&toolpaneview=2”打开设计页

    或者加“DisplayMode=Design

                http://Site/_layouts/spcontnt.aspx?&url=/_catalogs/wp/forms/editForm.aspx这页面是维护页面

    “超链接或图片”类型栏的值,对应的对象模型为SPFieldUrlSPFieldUrlValue,可以这样读取:

    SPFieldUrlValue value = new SPFieldUrlValue(item["URL"].ToString());

           Console.WriteLine(value.Description);

           Console.WriteLine(value.Url);

    SPFieldUrl fieldUrl = (SPFieldUrl)item.Fields["URL"];

    SPFieldUrlValue value = (SPFieldUrlValue)fieldUrl.GetFieldValue(item["URL"].ToString());

    Console.WriteLine(value.Description);

    Console.WriteLine(value.Url);

    赋值

                SPFieldUrl fieldUrl = (SPFieldUrl)supplierNew.Fields[dgi.Cells[0].Text];

        SPFieldUrlValue fieldUrlValue = new SPFieldUrlValue();

         fieldUrlValue.Url = web.Url + "/" + supplierDocument.RootFolder.Url + "/" + supplierNew["Title"].ToString() + "-" + supplierNew.ID;

        fieldUrlValue.Description = dgi.Cells[0].Text;

        supplierNew[dgi.Cells[0].Text] = fieldUrlValue;

     

    将子网站移动到主网站???

    修改子网站下的网站栏到网站集下解决了,直接到WSS_Content数据库里面,修改表ContentTypesScope字段,特别方便,暂时没发现出错误~

     

    如何定义一个Group

          SPGroupCollection groups = oWebsite.SiteGroups;

         SPUser user = oWebsite.Users["xxx""xxxxxx"];

         SPMember member = oWebsite.Users["xxxxx""xxx"];

    groups.Add("TestGroup", member, user, "Description");

     

    将一个Group分配进一个Role

    if (SPWeb.HasUniqueRoleAssignments == true)//web是否有自己的角色分配,有True

                        {

                            SPWeb.AllowUnsafeUpdates = true;

                            SPRoleAssignment roleAssign = new SPRoleAssignment((SPPrincipal)SPSite.RootWeb.SiteGroups["Style Resource Readers"]);

                            SPRoleDefinition roleDef = SPWeb.RoleDefinitions["Open Access"];

                            roleAssign.RoleDefinitionBindings.Add(roleDef);

                            SPWeb.RoleAssignments.Add(roleAssign);

                        }

    读取User Profile

    ServerContext spcontext2 = ServerContext.GetContext(site);

                        UserProfileManager profileManager = new UserProfileManager(spcontext2);

                        string userName = member.Name;

                        SPListItem newMember = projectMember.Items.Add();

                        newMember["User Name"] = member.Name;

                        newMember["Project"] = Project;

                        newMember["Group"] = newGroup.Name;

                        newMember["E-mail Address"] = member.Email;

                        if (profileManager.UserExists(userName))

                        {

                           UserProfile profile = profileManager.GetUserProfile(userName);

                           newMember["Business Phone"] = profile["BusinessPhone"].Value;

                           newMember["Mobile Phone"] = profile["CellPhone"].Value;

                           newMember["Fax"] = profile["Fax"].Value;

                           //newMember["Notes"] = member[PropertyConstants.CellPhone].

                           newMember["SkypeMSN"] = profile["SkypeMSN"].Value;

                           newMember["Principalship"] = profile["Principalship"].Value;

                           newMember["Location"] = profile["Location"].Value;

                        }

                        newMember.Update();

    关闭EventHandler

    this.DisableEventFiring();//关闭EventHandler,防止多重触发

    //save changes

    addedItem.Update();

    this.EnableEventFiring();

    workflowProperties.OriginatorUser得到当前workflow instance的发起者

    SharePoint中访问AD

    System.DictionaryService

    SPMenu 导航栏

  • 相关阅读:
    实验九:异常的抛出、捕获并处理
    声明圆锥体类,实现Area和Volume接口,计算表面积和体积,按体积比较大小。
    实验7:Student类继承Person类,并增加查找,统计功能
    类的封装:实现银行账户信息的开户,存款,取款,查询,销户操作
    输入包含十个整形类型数据的数组,将其升序排序,并输出其中的素数
    采用两个一维数组输出等腰三角形的杨辉三角
    log4net
    分页
    C#多线程编程(1):线程的启动
    把一个项目a生成后放在另一个项目b使用(b项目是例子中的ScreenWebPage_Tool)
  • 原文地址:https://www.cnblogs.com/Areas/p/2244299.html
Copyright © 2020-2023  润新知